r error 4 (Error in eval(ele) : objeto ‘opts_knit’ no encontrado )

Introducción

El método de series temporales jerárquicas es una técnica avanzada utilizada para modelar y predecir datos temporales que exhiben una estructura jerárquica natural. Su aplicación eficaz puede mejorar significativamente la precisión de los pronósticos y facilitar la toma de decisiones estratégicas en diversas áreas de aplicación, es especialmente útil en situaciones donde los datos se pueden descomponer en múltiples niveles de agregación, como por ejemplo, desplazamientos internos, regiones y país.

Componentes Principales

  1. Descomposición Jerárquica: Divide los datos en múltiples series temporales interrelacionadas que se organizan en una estructura de árbol jerárquico. Por ejemplo, los desplazamientos internos pueden descomponerse en desplazamientos internos por región, y a su vez, los desplazamientos internos por región se descomponen por estados.

  2. Modelado Independiente y Consistente: Cada serie temporal dentro de la jerarquía se modela de forma independiente utilizando métodos de series temporales tradicionales como ARIMA o métodos más avanzados como modelos de espacio de estado.

  3. Consistencia Agregada: Los pronósticos de las series temporales individuales se agregan de manera coherente para generar pronósticos precisos y consistentes en todos los niveles de la jerarquía.

Consideraciones Prácticas

  • Software Especializado: Utilización de herramientas como R (con paquetes como hts) o Python para implementar y automatizar el método.
  • Validación y Ajuste: Validar los modelos en múltiples niveles de la jerarquía y ajustar según sea necesario para mejorar la precisión.

Encuesta Nacional de Ocupación y Empleo (ENOE)

La Encuesta Nacional de Ocupación y Empleo (ENOE), realizada por el Instituto Nacional de Estadística y Geografía (INEGI), es una herramienta esencial para medir la dinámica del mercado laboral en México. Proporciona datos detallados sobre la ocupación, el empleo, el desempleo y otras características relevantes de la población económicamente activa.

Objetivos Principales

  1. Medición de la Población Económicamente Activa (PEA): Identificar la proporción de la población que participa en el mercado laboral, incluyendo tanto a las personas ocupadas como a las desocupadas.

  2. Análisis del Empleo: Proporcionar información sobre las características del empleo, incluyendo la naturaleza del trabajo, las condiciones laborales, los sectores económicos y las tasas de empleo formal e informal.

  3. Evaluación del Desempleo: Estimar la tasa de desempleo y analizar las características de la población desocupada, incluyendo la duración del desempleo y los esfuerzos de búsqueda de empleo.

  4. Información Socioeconómica: Recopilar datos sobre la educación, los ingresos y otras variables socioeconómicas que afectan y son afectadas por el empleo y el desempleo.

Componentes Principales

  • Encuestas Trimestrales: La ENOE se realiza de manera continua, con resultados publicados trimestralmente, lo que permite un seguimiento cercano de las tendencias laborales.
  • Cobertura Nacional: La encuesta abarca todas las entidades federativas de México, ofreciendo una visión comprensiva y detallada del mercado laboral a nivel nacional y regional.
  • Amplitud de Temas: Incluye información sobre empleo formal e informal, subempleo, ocupaciones, ingresos, condiciones de trabajo y más.

Aplicaciones

  • Políticas Públicas: Los datos de la ENOE son cruciales para la formulación y evaluación de políticas laborales, educativas y económicas.
  • Investigación Académica: Proporciona una base de datos rica para estudios sobre el mercado laboral, la economía del trabajo y la sociología del empleo.
  • Análisis Sectorial: Ayuda a identificar tendencias y desafíos específicos en distintos sectores económicos, informando decisiones empresariales y gubernamentales.

Consideraciones Prácticas

  • Acceso a Datos: Los datos de la ENOE están disponibles públicamente a través del INEGI, facilitando su uso para análisis y estudios detallados.
  • Metodología Rigurosa: La encuesta sigue estándares metodológicos estrictos, asegurando la calidad y confiabilidad de los datos.
  • Actualización Continua: La ENOE se actualiza continuamente, permitiendo un monitoreo preciso de las dinámicas laborales a lo largo del tiempo.

Diseño conceptual

La población objetivo de la encuesta está conformada por todos los que residen habitualmente las viviendas seleccionadas. Los instrumentos de captación más importantes son el Cuestionario Sociodemográfico (CS) y el Cuestionario de Ocupación y Empleo (COE). La información referente a los hogares y a las características sociodemográficas de los residentes de la vivienda se registra en el CS, mientras que el COE contiene variables que identifican en primer lugar la condición de actividad y en segundo término preguntas específicas para cada uno de los universos. Es necesario mencionar que el COE se levanta a la población de 12 años en adelante, sin embargo, por cuestiones metodológicas del marco de la OCDE se pública para la población de 15 años en adelante.

Diseño temporal

La ENOE es una encuesta panel de rotatorio, es decir, tiene una muestra de viviendas dividida en 5 paneles de rotación. De los cuales, rota uno cada trimestre; conservando de esta manera, el 80 por ciento de la muestra entre dos trimestres consecutivos. Lo que permite llevar a cabo dos importantes actividades: sustituir el marco muestral y cambiar esquema de muestreo.

Por otra parte, toda la cantidad de información recabada de la misma unidad de muestreo en dos o más periodos consecutivos permitirá teóricamente incrementar la precisión de las estimaciones, principalmente del cambio en ellas. Cochran (1977) coincide con esto y además establece que, en la obtención de las estimaciones actuales, se gana la misma precisión si se conserva la muestra inicial o se cambia en cada ocasión.

Condición de Residencia

Un aspecto relevante por considerar fue identificar la condición de residencia, a quienes de los residentes continuaban viviendo en el hogar o en otros términos a quienes no han estado en un proceso de transición de residencia, así como los ausentes definitivos y a los nuevos residentes. Al respecto, cabe acotar, que el diseño conceptual del Cuestionario Sociodemográfico identifica a quienes ya no se encuentran por haber partido a otro lugar por diversas causas entre éstas por mortalidad (Ausentes Definitivos) y distingue quienes son nuevos en lo del mismo hogar por haber arribado de algún lugar otro lugar por diversas causas entre ellas el nacimiento (Nuevo Residentes).

Motivo de la migración 1

Los datos son recopilados de la ENOE, siendo, la fuente principal de información sobre el mercado laboral mexicano al ofrecer datos de manera trimestral de la fuerza de trabajo, ocupación, la informalidad laboral, la subocupación y desocupación.

La ENOE inicia su levantamiento en 2005 y se repite en intervalos regulares de tiempo, captando la información a nivel nacional. Este tipo de encuesta permite captar y conocer de mejor manera las características socioeconómicas de la población mexicana de 15 años y más.

El objetivo del trabajo es implementar y comparar las diferentes series de tiempo de manera jerárquica y permitir el desglose de las causas de migración.

Indicadores

Tomando las preguntas del cuestionario de las cuales son más de trescientas bases de datos con 150 mil casos a nivel nacional en los diferentes periodos de tiempo.

Las coberturas geográficas o dominios de estudio para las cuales se generan estimaciones son:

  • Ciudad Autorepresentada
  • Entidad Federativa
  • Nacional

Se toma como referencia la pregunta cs_ad_mot Motivo de la migración , en la cual se desglosa en las siguientes categorías.

  • Trabajo
  • Estudio
  • Se casó o unió
  • Se separó o divorció
  • Problemas de salud
  • Reunirse con la familia
  • Inseguridad pública
  • Falleció
  • Otro Motivo
  • No sabe

De las cuales solo se toman 5 casos para el propósito del presente trabajo.

Base de datos

Se cargan las bases de datos que contienen los cinco principales motivos de la migración, tomando como referencia los datos del 2005 al 2019.

  • (detectDates = TRUE); las fechas se detectan y se convierten automáticamente en objetos de fecha en R.
T.Trabajo <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
                       sheet = "Trabajo", 
                       colNames = TRUE, detectDates = TRUE)
T.Estudio <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"), 
                       sheet = "Estudio",
                       colNames = TRUE, 
                       detectDates = TRUE)
T.Union <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"),
                     sheet = "Union",
                     colNames = TRUE, 
                     detectDates = TRUE)
T.Divorcio <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"), 
                        sheet = "Divorcio", 
                        colNames = TRUE, 
                        detectDates = TRUE)
T.Familia <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"), 
                       sheet = "Reunirse con un familiar", 
                       colNames = TRUE, 
                       detectDates = TRUE)

Se divide entre la población, debido a que si toman los absolutos de las personas que cambiaron de residencia por alguno de los diferentes motivos de ausencia. Estos tienden a ser mayores en algunas ciudades, debido se tiene mayor densidad de población. Permitiendo así la comparabilidad entre ciudades por una razón de cada 1000 personas.

Se define la función llamada divide_columns que toma dos data.frames (df1 y df2). La función:

  • Extrae todas las columnas de df1 y df2 desde la segunda columna en adelante.
  • Usa la función map2_dfc del paquete purrr para dividir cada par de columnas correspondientes de df1 y df2, multiplicando el resultado por 1000.
  • Se reconstruye el data.frame resultante combinando la primera columna de df1 con las columnas resultantes de la división.
#Población Total  
T.Poblacion <- read.xlsx(paste0(here::here(), "/Base de datos/Resultados ENOE.xlsx"), 
                         sheet = "Población", 
                         colNames = TRUE, 
                         detectDates = TRUE)
# Vector de tiempo
Periodo <- T.Poblacion$Periodo #Se guarda el vector tiempo

#Creamos una función personalizada para dividir los elementos desde la segunda columna en adelante
divide_columns <- function(df1, df2) {
                    df1_cols <- df1[, 2:ncol(df1)]
                    df2_cols <- df2[, 2:ncol(df2)]
                    
                    # Aplicamos la división usando map2
                    result_cols <- map2_dfc(df1_cols, df2_cols, ~ .x / .y * 1000)
                    
                    # Reconstruimos el data.frame con la primera columna de df1 y las columnas resultantes
                    result <- bind_cols(df1[, 1, drop = FALSE], result_cols)
                    result
}

tablas <- ls(pattern = "T.")
for(i in 1:6){
  assign(paste0(tablas[i]), divide_columns(get(paste0(tablas[i])), T.Poblacion))
}
# Todo en un data.frame
mydata <- do.call(cbind.data.frame, list(T.Trabajo,
                                         T.Estudio %>% select(-c("Periodo")) ,
                                         T.Union %>% select(-c("Periodo")) ,
                                         T.Divorcio %>% select(-c("Periodo")) ,
                                         T.Familia %>% select(-c("Periodo"))))
Tasas de migración por algún motivo de ausencia
Periodo Centro_ACA_Trabajo Centro_CUER_Trabajo Centro_MEX_Trabajo Centro_PACH_Trabajo Centro_PUE_Trabajo
2005-01-01 8076 4255 67493 2228 6201
2005-04-01 7798 4651 76577 2584 8752
2005-07-01 4224 3123 43216 1135 4350
2005-10-01 2057 2360 23673 1013 5130
2006-01-01 4624 3006 22306 1066 4730
2006-04-01 2624 2530 36413 1073 2832

A continuación se estructura la jerarquía de los niveles de acuerdo al tipo de desagregación geográfica, en la cual se agrupan las 32 ciudades autorepresentadas en regiones.
- Se consideraron 5 regiones del país para que los cálculos no fueran tan extensos a la hora de interpretarlos.

Estructura general de las regiones
Región Clave Ciudad
Centro 11 Acapulco
Centro 24 Cuernavaca
Centro 01 México
Centro 32 Pachuca
Centro 04 Puebla
Centro 14 Toluca
Centro 29 Tlaxcala
Noreste 21 Durango
Noreste 03 Monterrey
Noreste 06 San Luis Potosí
Noreste 15 Saltillo
Noreste 09 Tampico
Noroeste 08 Chihuahua
Noroeste 19 Culiacán
Noroeste 20 Hermosillo
Noroeste 30 La Paz
Noroeste 18 Tijuana
Occidente 12 Aguascalientes
Occidente 27 Colima
Occidente 02 Guadalajara
Occidente 05 León
Occidente 13 Morelia
Occidente 28 Querétaro
Occidente 22 Tepic
Occidente 26 Zacatecas
Sureste 31 Cancún
Sureste 23 Campeche
Sureste 07 Mérida
Sureste 25 Oaxaca
Sureste 17 Tuxtla Guutiérrez
Sureste 10 Veracruz
Sureste 16 Villahermosa

Estructura jerárquica

Cada uno de estos grupos se desglosan en categorías que están anidadas dentro de las categorías de grupos más grandes como 32 ciudades autorepresentadas y 5 regiones, por lo que se hace una recolección de 160 series de tiempo que siguen una estructura de agregación jerárquica.

Esquema Jerárquico
Esquema Jerárquico

El número de series en el nivel inferior es de 160 series, por lo que las observaciones en el nivel último sumaran a las observaciones del nivel anterior y así sucesivamente.

Los 5 motivos de la ausencia se transforman en series de tiempo, para analizarlos cada uno posteriormente. Los datos se convierten en objetos de series temporales (ts) utilizando la función ts. Cada serie temporal se define con:

  • start = 2005: El primer año de la serie temporal es 2005.
  • end = 2019: El último año de la serie temporal es 2019.
  • frequency = 4: La frecuencia de la serie temporal es trimestral (4 trimestres por año).
ts.Trabajo <- ts(T.Trabajo %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Estudio <- ts(T.Estudio %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Union <- ts(T.Union %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Divorcio <- ts(T.Divorcio %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)
ts.Familia <- ts(T.Familia %>% select(., c(2:length(.))), start = 2005, end = 2019, frequency = 4)

Motivo de la ausencia: Trabajo

Se analiza cómo caso particular el motivo de la ausencia por trabajo, para empezar familiarizarse con la jerarquización del modelo y posteriormente agregar de manera general los demás motivos expuestos al inicio.

Utilizando la función dygraph permite observar de manera iterativa multiples series de tiempo.

  • dyRangeSelector(): Agrega un selector de rango (un control deslizante) que permite al usuario seleccionar un rango de fechas para visualizar en el gráfico.
  • dyLegend(width = 650): Añade una leyenda al gráfico y establece su ancho a 650 píxeles.
  • dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")): Personaliza los colores de las series en el gráfico utilizando la paleta de colores “Set2” de RColorBrewer, que proporciona una paleta de 32 colores.
  • dyHighlight(highlightSeriesOpts = list(strokeWidth = 2)): Permite resaltar las series en el gráfico cuando el usuario pasa el cursor sobre ellas. strokeWidth = 2 establece el grosor de la línea resaltada a 2 píxeles.
G.Trabajo <- dygraph(ts.Trabajo, main = "Trabajo",  ylab = "Migrantes", xlab = "Periodo") %>%
              dyRangeSelector() %>%
               dyLegend(width = 650) %>%
                dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
                 dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Trabajo

A continuación, se presenta de manera desagregada un análisis descriptivo de las 32 ciudades autorepresentadas.

Análisis descriptivo: Motivo de trabajo
vars n mean sd median trimmed mad min max range skew kurtosis se
Centro_ACA_Trabajo 1 60 3276.68 1229.07 3073.0 3128.54 704.24 1421 8076 6655 1.87 4.93 158.67
Centro_CUER_Trabajo 2 60 2076.98 799.35 2010.0 2008.62 685.70 778 4651 3873 0.89 0.92 103.20
Centro_MEX_Trabajo 3 60 36437.75 12699.62 35751.5 35338.75 11613.21 16225 76577 60352 0.84 0.93 1639.51
Centro_PACH_Trabajo 4 60 1328.42 393.88 1313.0 1305.79 378.06 452 2584 2132 0.60 0.75 50.85
Centro_PUE_Trabajo 5 60 3720.97 1334.62 3620.5 3623.44 1476.67 1687 8752 7065 0.99 1.76 172.30
Centro_TOL_Trabajo 6 60 1460.93 808.15 1252.0 1360.29 570.06 163 4234 4071 1.21 1.39 104.33
Centro_TLAX_Trabajo 7 60 2004.47 664.00 2004.5 1951.81 507.05 927 4742 3815 1.27 3.35 85.72
Noreste_DUR_Trabajo 8 60 1302.52 653.81 1226.0 1232.54 578.21 385 3742 3357 1.39 2.86 84.41
Noreste_MTY_Trabajo 9 60 6180.50 2139.86 5990.0 6042.71 1902.92 2373 12892 10519 0.67 0.64 276.25
Noreste_SLP_Trabajo 10 60 2271.88 1030.52 2066.0 2180.46 722.03 373 6524 6151 1.36 3.31 133.04
Noreste_SLT_Trabajo 11 60 1107.57 612.45 975.5 1039.02 415.13 219 4132 3913 2.53 9.51 79.07
Noreste_TAM_Trabajo 12 60 2560.93 753.01 2504.5 2490.02 526.32 1241 4933 3692 1.03 1.31 97.21
Noroeste_CHIH_Trabajo 13 60 1891.30 956.51 1845.0 1785.42 631.59 314 5577 5263 1.49 3.41 123.48
Noroeste_CUL_Trabajo 14 60 1369.95 619.08 1201.5 1265.06 447.75 616 3549 2933 1.52 2.16 79.92
Noroeste_HER_Trabajo 15 60 1761.20 691.17 1625.5 1666.98 418.83 721 4428 3707 1.81 4.22 89.23
Noroeste_PAZ_Trabajo 16 60 683.58 275.34 622.5 659.85 259.46 255 1334 1079 0.71 -0.29 35.55
Noroeste_TIJ_Trabajo 17 60 4250.72 1605.87 4250.0 4159.40 1555.25 971 8584 7613 0.53 0.46 207.32
Occidente_AGS_Trabajo 18 60 1253.98 545.25 1097.5 1197.27 352.86 310 3041 2731 1.21 1.66 70.39
Occidente_COL_Trabajo 19 60 839.73 261.77 804.0 821.60 284.66 346 1626 1280 0.64 -0.06 33.79
Occidente_GDL_Trabajo 20 60 6266.35 2037.18 6220.5 6153.10 1678.30 1689 13052 11363 0.68 1.26 263.00
Occidente_LN_Trabajo 21 60 1937.27 1153.90 1611.0 1738.67 679.03 692 7030 6338 2.39 7.01 148.97
Occidente_MOR_Trabajo 22 60 2327.93 679.93 2218.5 2288.12 617.50 1137 4755 3618 0.85 1.27 87.78
Occidente_QRT_Trabajo 23 60 2459.40 1041.07 2268.5 2339.35 876.96 903 5660 4757 1.04 0.89 134.40
Occidente_TEP_Trabajo 24 60 1445.45 443.35 1376.5 1401.23 381.77 687 2867 2180 0.90 0.64 57.24
Occidente_ZAC_Trabajo 25 60 535.97 243.95 488.5 510.15 176.43 154 1694 1540 1.93 6.56 31.49
Sureste_CANC_Trabajo 26 60 1909.12 681.59 1732.5 1866.08 613.80 814 4182 3368 0.79 0.70 87.99
Sureste_CAMP_Trabajo 27 60 400.65 178.63 362.0 386.21 151.97 84 968 884 0.84 0.68 23.06
Sureste_MER_Trabajo 28 60 1880.15 764.38 1789.0 1802.12 549.30 755 5452 4697 1.81 6.02 98.68
Sureste_OAX_Trabajo 29 60 1674.82 725.90 1590.5 1569.25 584.89 779 4725 3946 2.30 7.04 93.71
Sureste_TGTZ_Trabajo 30 60 1911.53 753.69 1651.0 1831.71 524.10 632 4188 3556 0.94 0.22 97.30
Sureste_VER_Trabajo 31 60 2038.40 720.73 1941.5 2015.21 700.53 364 3619 3255 0.20 -0.26 93.05
Sureste_VH_Trabajo 32 60 1181.52 398.62 1122.0 1151.38 348.41 339 2591 2252 0.90 1.44 51.46

Ejemplo: Por causas de trabajo la ciudad de Acapulco muestra una media de 4.62 personas que emigraron por trabajo de cada 1000 personas.

Serie de tiempo jerárquica

Se utiliza la función hts para crear una serie de tiempo jerárquica.

Definición de vectores:

  • Regiones: Un vector que contiene códigos de regiones repetidos para crear una etiqueta de región específica.
  • Ciudades: Un vector que contiene códigos de ciudades que se combinan con las regiones para crear nombres únicos.
  • Motivo: Un vector que contiene el motivo “Trabajo”, repetido para igualar la longitud de los otros vectores.

Creacion del nombre de columnas

Se utilizan los datos de último nivel y se utiliza el argumento characters donde los primeros dos caracteres corresponden al primer nivel (Región), los siguientes dos corresponden al segundo nivel (Ciudades) y como último los siete caracteres corresponden al motivo de la ausencia (Trabajo).

  • hts(ts.Trabajo, nodes = list(32), characters = c(2, 2, 7)): Crea un modelo jerárquico de series temporales (hts) a partir de ts.Trabajo.
  • nodes = list(32): Define un solo nivel en la jerarquía (nivel 1) con 32 nodos.
  • characters = c(2, 2, 7): Define la estructura de los nombres de las columnas en términos de caracteres para la región(2), ciudad(2) y motivo(7).
  • Modelo1$labels$Level 1 <- c("Centro", "Noreste", "Noroeste", "Sureste", "Occidente"): Asigna etiquetas a los nodos en el nivel 1 del modelo Modelo1. Estas etiquetas representan diferentes regiones o áreas geográficas en lugar de los códigos originales.
#Cambiamos los nombres de las columnas 
Regiones <- c(rep("CE", 7),
              rep("NE", 5), 
              rep("NW", 5), 
              rep("WE", 8),
              rep("SO", 7))
Ciudades <- c("11",     "24",   "01",  "32",    "04",   "14",   "29",   
              "21",     "03",   "06",   "15",   "09",   
              "08",     "19",   "20",   "30",   "18",   
              "12",     "27",   "02",   "05",   "13",   "28",   "22",   "26",   
              "31",     "23",   "07",   "25",   "17",   "10",   "16")
Motivo <- c(rep("Trabajo", 32))

nombres <- paste0(Regiones, Ciudades, Motivo) ## Largo de 11 /Regiones=2,Ciudades=2,Motivo=7
colnames(ts.Trabajo) <- nombres

#Nodos 
Modelo1 <- hts(ts.Trabajo, nodes = list(32), characters = c(2, 2, 7))

## Cambiamos las etiquetas 
Modelo1$labels$`Level 1` <- c("Centro", "Noreste", "Noroeste", "Sureste", "Occidente")
class(Modelo1)
[1] "hts" "gts"
summary(Modelo1)
Hierarchical Time Series 
4 Levels 
Number of nodes at each level: 1 5 32 32 
Total number of series: 70 
Number of observations per series: 57 
Top level series: 
       Qtr1   Qtr2   Qtr3   Qtr4
2005 181720 221684 125424  85399
2006  93376 114025 114634 106325
2007  88853 122836  96359  90540
2008  84774  95417  97380  70266
2009 107129 118041 111815  76948
2010  80878  80668  72698  86746
2011  80383  94402  71951  80582
2012 103653  78282  89342  94176
2013  90291  84373  97686  81500
2014  97991  95923 102743  93418
2015 104140 103351 114061 102196
2016 108697  89450 106471 107005
2017 123622  97961 145247  99029
2018  98958 105396 109788  81128
2019 102746                     

Labels: 
[1] "Level 0" "Level 1" "Level 2" "Level 3"
#p<-smatrix(Modelo1) #Resumen de la matriz de hierarquical time series
#q<-allts(Modelo1) #Matrix de todos los niveles

Nivel 1: Región

Se visualizan las series temporales agregadas de un modelo jerárquico de series temporales (Modelo1).

  • aggts(level = 1): Extrae las series temporales agregadas del nivel 1 del modelo Modelo1. El level = 1indica que se está extrayendo datos del nivel más alto en la jerarquía.
Modelo1 %>% 
 aggts(level = 1) %>%
  autoplot(size = 1) + 
   theme_classic() + 
    theme(plot.title = element_text(size = 20),
          plot.subtitle = element_text(size = 12),
          legend.text = element_text(size = 8),
          legend.key.size = unit(0.5, "lines")) +
     scale_color_viridis_d() + 
      scale_color_manual(values = RColorBrewer::brewer.pal(5, "Dark2")) + 
       scale_x_continuous(breaks = seq(2005, 2019, by = 3)) +
        labs(title = "Motivo de la ausencia 2005-2019",
             subtitle = "Trabajo",
             y = "Rate",
             x =  "Year",
             color = "Series") 
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

La gráfica superior muestra la tasa de migración por trabajo total por región. Donde se puede apreciar que la región Noreste y Noroeste presentan una menor moivilidad con respecto a las demás.

Nivel 2: Ciudad autorepresentada

A continuación se muetran los datos desglosados por las 32 ciudades.

  • aggts(level = 2): indica que se están extrayendo datos de un nivel de jerarquía inferior al nivel 1.
Modelo1 %>% 
 aggts(level = 2) %>%
  autoplot(size = 0.5) + 
   theme_classic() + 
    theme(plot.title = element_text(size = 20, family = "Century Gothic"),
          plot.subtitle = element_text(size = 12, family = "Century Gothic"),
          legend.text = element_text(size = 8, family = "Century Gothic"),
          legend.spacing.x = unit(0.1, "cm"),
          legend.key.size = unit(0.5, "lines"),
          legend.position = "bottom") +
     scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(60)) + 
      guides(col = guide_legend(ncol = 15)) +
       labs(title = "Motivo de la ausencia 2005-2019",
            subtitle = "Trabajo",
            y = "Rate",
            x = "Year",
            color = "Series") 

Si bien la gráfica anterior no permite su interpretabilidad debido a que todo el ensamble de las series están muy juntas.

Haciendo uso de la función aggts extrae las series temporales de un objeto hts para cualquier nivel de desagregación. Para aggts(Modelo1, level = 2), se especifica que queremos extraer las series temporales del nivel 2 del modelo jerárquico. Los niveles en un modelo jerárquico corresponden a diferentes niveles de agregación en la jerarquía de datos.

Para este caso, se están trabajando con dos niveles de desagregación (Regiones y Ciudades) y bien un Nivel Cero (Total).

groups <- aggts(Modelo1, level = 2)

En el siguiente gráfico se muestran las series de tiempo del nivel inferior, es decir, las tasas de migración por trabajo para cada una de las ciudades en sus respectivas regiones.

Ayudando así a visualizar de manera individual las series.

tibble::as_tibble(groups) %>%
 tidyr::gather(Series) %>%
  mutate(Date = rep(time(groups), NCOL(groups)),
         Group = stringr::str_extract(Series, "([A-Za-z ]*)")) %>%
   ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
    geom_line() + 
     theme_classic() +
      theme(plot.title = element_text(size = 20, family = "Century Gothic"),
            plot.subtitle = element_text(size = 12, family = "Century Gothic"),
            axis.text.x = element_text(angle = 90, hjust = 1, family = "Century Gothic"),
            legend.text = element_text(size = 8, family = "Century Gothic"),
            legend.spacing.x = unit(0.1, "cm"),
            legend.key.size = unit(0.5, "lines"),
            legend.position = "bottom") +
       scale_color_viridis_d() + 
       #scale_color_manual(values = colorRampPalette(brewer.pal(8, "Set2"))(33)) + 
        scale_x_continuous(breaks = seq(1980, 2015, by = 5)) +
         scale_y_continuous(labels = scales::comma) +
          guides(col = guide_legend(ncol = 15)) +
           labs(title = "Motivo de la ausencia 2005-2019",
                subtitle = "Trabajo",
                y = "Rate",
                x = "Year",
                color = "Grupos") +
            facet_wrap(. ~ Group)

Forecasting: Motivo de trabajo

Utilizando la función forecast() del paquete hts.

Se presentan tres opciones integradas para producir pronósticos usando el parámetro fmethod:

  • ETS Exponential Smoothing,
  • Modelos ARIMA
  • Caminatas aleatorias(RW).

Enfoques 2

  • Enfoque de abajo hacia arriba “bottom-up”(method= "bu"): Pronostica del nivel más bajo de la jerarquía, es decir, los motivos de ausencia y luego va agregando los resultados a la jerárquía generar el pronostico del nivel superior al último.

  • Enfoque de arriba hacia abajo “top-down” (method= "tdfp"): Pronostica en la jerarquía del nivel más alto, es decir, por regiones y luego va desglosando los resultados en la jerarquía.

  • Enfoque intermedio **“middle-out” (method= "mo"): Combina enfoques ascendentes y descendentes. Primero, se elige un “nivel medio” y se generan pronósticos para todas las series en este nivel. Para las series por encima del nivel medio, se generan pronósticos coherentes utilizando el enfoque de abajo hacia arriba agregando los pronósticos de “nivel medio” hacia arriba. Para las series por debajo del “nivel medio”, se generan pronósticos coherentes utilizando un enfoque de arriba hacia abajo al desglosar los pronósticos de “nivel medio” hacia abajo.

  • method = "tdfp": Especifica el método de pronóstico a utilizar. “tdfp” se refiere a “top-down forecasting using a detailed forecast procedure”. Este método realiza el pronóstico a nivel más detallado primero y luego agrega los pronósticos hacia los niveles superiores de la jerarquía.

  • h = 4: Define el horizonte de pronóstico. En este caso, se está pronosticando 4 períodos hacia el futuro.

  • keep.fitted = TRUE: Mantiene los valores ajustados del modelo para su análisis posterior, lo cual puede ser útil para evaluar el rendimiento del modelo.

#h<<-forecast horizon
#method= "mo"<<-"middle-out"
f.modelo1 <- forecast(Modelo1, h = 4, method = "tdfp", fmethod = "ets", parallel = TRUE, keep.fitted = TRUE)
class(f.modelo1)
[1] "hts" "gts"
#summary(f.modelo1)

Nivel 0 al 2

Se extraen las series temporales para los niveles 0, 1 y 2 tanto del modelo de pronóstico (fcst1) como del modelo original (groups). Esto te permitirá comparar los datos originales con los pronósticos generados a diferentes niveles de la jerarquía.
- levels = 0:2: Especifica que se deben extraer las series temporales para los niveles 0, 1 y 2 del modelo jerárquico.

fcst1 <- aggts(f.modelo1, levels = 0:2)
groups <- aggts(Modelo1, levels = 0:2)

Se visualizan tanto las series temporales pronosticadas (fcst1) como las series temporales originales (groups).

autoplot(fcst1, size = 0.5) +
 autolayer(groups) +
  geom_vline(xintercept = 2019, color = "#A8ABD7", linetype= "dashed") +
   theme_classic() +
    theme(plot.title = element_text(size = 18, family = "Century Gothic"),
          plot.subtitle = element_text(size = 14, family = "Century Gothic"),
          legend.text = element_text(size = 7, family = "Century Gothic"),
          legend.key.size = unit(0.5, "lines"),
          legend.position = "bottom") +
     scale_color_viridis_d() + 
      scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
       scale_y_continuous(labels = scales::comma) +
        guides(col = guide_legend(ncol = 15))+
         labs(title = "Motivo de la ausencia 2005-2019",
              subtitle = "Trabajo",
              y = "Rate",
              x = "Year",
              color = "Series") 
For a multivariate time series, specify a seriesname for each time series. Defaulting to column names.

Ahora bien, se combinan las series temporales originales y los pronósticos en una sola serie temporal, manteniendo la misma frecuencia y punto de partida que las series originales.

tabla <- ts(rbind(groups, fcst1), start = start(groups), frequency = 4)

Nivel Total: Por motivo de trabajo

A continuación se muetran los datos desglosados a nivel Nacional.

#http://www.sthda.com/english/wiki/ggplot2-line-types-how-to-change-line-types-of-a-graph-in-r-software
autoplot(tabla[, "Total"], colour =  "#1720B7", size = 1.2, alpha = 0.6, linetype = "dashed") +
 geom_vline(xintercept = 2019.5, color = "#A8ABD7", linetype = "dashed") +
  theme_classic() +
   scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
    labs(title = "Motivo de la ausencia 2005-2019",
         subtitle = "Trabajo",
         y = "Rate",
         x =  "Year",
         color = "Series") 
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.

as_tibble(tabla[,-1]) %>%
 tidyr::gather(Series) %>%
  mutate(Date = rep(time(tabla), NCOL(tabla)-1),
         Group = str_extract(Series, "([A-Za-z ]*)")) %>%
   ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
    geom_line() +
     geom_vline(xintercept = 2017, color = "#A8ABD7", linetype = "dashed") +
      theme_classic() + 
       theme(plot.title = element_text(size = 18, family = "Century Gothic"),
             plot.subtitle = element_text(size = 14, family = "Century Gothic"),
             axis.text.x = element_text(angle = 90, hjust = 1, family = "Century Gothic"),
             legend.position = "bottom",
             legend.text = element_text(size = 8, family = "Century Gothic"),
             legend.key.size = unit(0.5, "lines")) +
        scale_color_viridis_d() +
         scale_x_continuous(breaks = seq(1985, 2025, by = 10)) +
          guides(col = guide_legend(ncol = 15))+
           labs(title = "Motivo de la ausencia 2005-2019",
                subtitle = "Trabajo",
                y = "Rate",
                x = "Year",
                color = "Series") +
            facet_wrap(.~Group) 

Se extraen las series temporales para los niveles 0, 1 y 2 tanto del modelo de pronóstico (f.modelo1). Esto te permitirá comparar los datos originales con los pronósticos generados a diferentes niveles de la jerarquía.

  • levels = 0:2: Especifica que se deben extraer las series temporales para los niveles 0, 1 y 2 del modelo jerárquico.
f.modelo1 %>% 
 aggts(levels = 0:2) %>%
  autoplot(facet = FALSE) + 
   theme_classic() +
    theme(plot.title = element_text(size = 18, family = "Century Gothic"),
          plot.subtitle = element_text(size = 14, family = "Century Gothic"),
          legend.text = element_text(size = 7, family = "Century Gothic"),
          legend.key.size = unit(0.5, "lines")) +
     scale_color_viridis_d() +
      labs(title = "Motivo de la ausencia 2005-2019",
           subtitle = "Trabajo",
           y = "Rate",
           x = "Year",
           color = "Series")

Motivos de ausencia en general

Utilizando los 5 motivos de ausencia: - Trabajo
- Estudio
- Se casó o unió
- Se separó o divorció
- Reunirse con la familia

Serie de tiempo

Los datos de la estructura general se convierten en objetos de series temporales (ts) utilizando la función ts. Cada serie temporal se define con:

  • start = 2005: El primer año de la serie temporal es 2005.
  • end = 2019: El último año de la serie temporal es 2019.
  • frequency = 4: La frecuencia de la serie temporal es trimestral (4 trimestres por año).
ts.mydata <- ts(mydata %>% select(., c(2:ncol(.))), start = 2005, end = 2019, frequency = 4)

Series de tiempo por motivos de la migración

Motivo de trabajo

G.Trabajo <- dygraph(ts.Trabajo, main = "Trabajo", ylab = "Migrantes", xlab = "Periodo") %>%
              dyRangeSelector() %>%
               dyLegend(width = 650) %>%
                dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
                 dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Trabajo

Motivo de estudio

G.Estudio <- dygraph(ts.Estudio, main = "Estudio", ylab = "Migrantes", xlab = "Periodo") %>%
              dyRangeSelector() %>%
               dyLegend(width = 650) %>%
                dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
                 dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Estudio
Analisis descriptivo: Estudio
vars n mean sd median trimmed mad min max range skew kurtosis se
Centro_ACA_Estudio 1 60 0.78 0.46 0.68 0.73 0.51 0.00 1.93 1.93 0.70 -0.22 0.06
Centro_CUER_Estudio 2 60 0.34 0.30 0.23 0.31 0.19 0.00 1.11 1.11 0.89 -0.30 0.04
Centro_MEX_Estudio 3 60 0.31 0.21 0.28 0.29 0.19 0.00 0.91 0.91 0.77 0.02 0.03
Centro_PACH_Estudio 4 60 1.01 0.54 0.94 0.96 0.46 0.23 2.89 2.65 1.10 1.95 0.07
Centro_PUE_Estudio 5 60 0.31 0.27 0.25 0.27 0.19 0.00 1.45 1.45 1.94 4.77 0.03
Centro_TOL_Estudio 6 60 0.24 0.18 0.21 0.22 0.15 0.00 0.76 0.76 0.95 0.60 0.02
Centro_TLAX_Estudio 7 60 0.55 0.36 0.52 0.52 0.36 0.00 1.55 1.55 0.74 -0.19 0.05
Noreste_DUR_Estudio 8 60 0.45 0.35 0.42 0.42 0.37 0.00 1.33 1.33 0.67 -0.42 0.04
Noreste_MTY_Estudio 9 60 0.36 0.19 0.34 0.35 0.20 0.00 0.94 0.94 0.66 0.27 0.02
Noreste_SLP_Estudio 10 60 0.46 0.30 0.42 0.44 0.29 0.00 1.25 1.25 0.51 -0.42 0.04
Noreste_SLT_Estudio 11 60 0.44 0.48 0.36 0.35 0.32 0.00 2.66 2.66 2.49 7.71 0.06
Noreste_TAM_Estudio 12 60 0.66 0.50 0.54 0.60 0.42 0.00 1.97 1.97 1.01 0.35 0.06
Noroeste_CHIH_Estudio 13 60 0.36 0.26 0.31 0.34 0.24 0.00 1.20 1.20 0.70 0.25 0.03
Noroeste_CUL_Estudio 14 60 0.54 0.31 0.52 0.54 0.36 0.00 1.19 1.19 0.10 -0.93 0.04
Noroeste_HER_Estudio 15 60 0.71 0.38 0.64 0.68 0.28 0.00 1.65 1.65 0.63 -0.16 0.05
Noroeste_PAZ_Estudio 16 60 1.12 0.55 1.07 1.08 0.54 0.16 2.39 2.22 0.45 -0.43 0.07
Noroeste_TIJ_Estudio 17 60 0.47 0.39 0.42 0.43 0.35 0.00 2.04 2.04 1.57 3.48 0.05
Occidente_AGS_Estudio 18 60 0.36 0.26 0.28 0.34 0.23 0.00 0.95 0.95 0.64 -0.34 0.03
Occidente_COL_Estudio 19 60 0.84 0.46 0.77 0.81 0.40 0.00 2.15 2.15 0.57 0.24 0.06
Occidente_GDL_Estudio 20 60 0.30 0.22 0.24 0.27 0.19 0.00 1.03 1.03 0.96 0.42 0.03
Occidente_LN_Estudio 21 60 0.23 0.18 0.18 0.21 0.14 0.00 0.72 0.72 0.85 0.18 0.02
Occidente_MOR_Estudio 22 60 0.59 0.41 0.56 0.56 0.45 0.00 1.64 1.64 0.53 -0.65 0.05
Occidente_QRT_Estudio 23 60 0.43 0.35 0.34 0.40 0.43 0.00 1.35 1.35 0.63 -0.35 0.04
Occidente_TEP_Estudio 24 60 0.88 0.42 0.82 0.86 0.37 0.00 2.10 2.10 0.45 0.50 0.05
Occidente_ZAC_Estudio 25 60 0.66 0.38 0.67 0.64 0.38 0.00 2.00 2.00 0.86 1.72 0.05
Sureste_CANC_Estudio 26 60 0.92 0.44 0.90 0.89 0.39 0.00 2.12 2.12 0.57 0.02 0.06
Sureste_CAMP_Estudio 27 60 0.44 0.29 0.39 0.43 0.31 0.00 1.33 1.33 0.59 0.16 0.04
Sureste_MER_Estudio 28 60 0.40 0.31 0.32 0.36 0.26 0.00 1.33 1.33 1.03 0.59 0.04
Sureste_OAX_Estudio 29 60 1.13 0.59 0.95 1.09 0.55 0.08 2.57 2.49 0.53 -0.57 0.08
Sureste_TGTZ_Estudio 30 60 0.65 0.35 0.61 0.63 0.31 0.00 1.60 1.60 0.58 -0.20 0.04
Sureste_VER_Estudio 31 60 0.40 0.33 0.33 0.37 0.28 0.00 1.25 1.25 0.64 -0.58 0.04
Sureste_VH_Estudio 32 60 0.97 0.53 0.85 0.93 0.44 0.13 2.29 2.16 0.63 -0.45 0.07

Motivo se unió o casó

G.Union <- dygraph(ts.Union, main = "Se unió o casó", ylab = "Migrantes", xlab = "Periodo") %>%
            dyRangeSelector() %>%
             dyLegend(width = 650) %>%
              dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
               dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Union
Analisis descriptivo: Se unió o casó
vars n mean sd median trimmed mad min max range skew kurtosis se
Centro_ACA_Union 1 60 1282.68 570.69 1244.0 1242.33 441.81 225 3951 3726 1.93 7.20 73.68
Centro_CUER_Union 2 60 1636.95 542.44 1712.0 1634.42 514.46 465 2925 2460 0.00 -0.60 70.03
Centro_MEX_Union 3 60 39873.95 12726.17 38255.5 38218.60 7503.44 22549 100291 77742 2.42 8.32 1642.94
Centro_PACH_Union 4 60 707.23 281.13 660.5 678.58 220.91 252 1543 1291 0.91 0.46 36.29
Centro_PUE_Union 5 60 4436.13 1357.04 4396.5 4361.19 1302.46 1726 7776 6050 0.44 -0.16 175.19
Centro_TOL_Union 6 60 2453.82 735.09 2475.5 2437.10 864.36 1122 4200 3078 0.14 -0.73 94.90
Centro_TLAX_Union 7 60 1537.23 585.80 1562.5 1475.52 352.12 571 4370 3799 2.25 8.29 75.63
Noreste_DUR_Union 8 60 1307.10 458.62 1202.0 1253.83 350.63 504 3378 2874 1.77 5.34 59.21
Noreste_MTY_Union 9 60 10975.08 2529.97 10741.0 10734.12 2431.46 7268 19391 12123 0.91 1.00 326.62
Noreste_SLP_Union 10 60 2435.90 909.59 2378.5 2385.60 943.67 938 4568 3630 0.36 -0.52 117.43
Noreste_SLT_Union 11 60 2186.33 671.94 2096.0 2125.79 478.88 850 4580 3730 1.07 2.05 86.75
Noreste_TAM_Union 12 60 1545.40 455.18 1489.5 1525.00 470.73 743 2624 1881 0.40 -0.64 58.76
Noroeste_CHIH_Union 13 60 2441.02 808.19 2353.5 2402.46 887.34 906 4877 3971 0.46 -0.02 104.34
Noroeste_CUL_Union 14 60 2049.72 858.11 1933.5 1935.33 650.12 679 5546 4867 2.05 5.86 110.78
Noroeste_HER_Union 15 60 1948.65 578.75 1914.5 1899.52 617.50 995 3709 2714 0.84 0.45 74.72
Noroeste_PAZ_Union 16 60 561.07 212.86 539.5 549.96 230.54 92 1372 1280 0.85 1.98 27.48
Noroeste_TIJ_Union 17 60 4458.73 1450.91 4398.5 4373.35 1598.98 1498 8456 6958 0.42 -0.21 187.31
Occidente_AGS_Union 18 60 2061.78 568.70 2010.0 2018.54 505.57 1044 3739 2695 0.81 0.94 73.42
Occidente_COL_Union 19 60 718.90 273.00 656.5 681.00 216.46 367 1949 1582 2.02 5.92 35.24
Occidente_GDL_Union 20 60 10166.35 2742.03 9626.0 9980.56 2641.99 5099 17555 12456 0.62 -0.09 353.99
Occidente_LN_Union 21 60 3688.92 1022.98 3420.0 3580.40 781.33 2193 7331 5138 1.34 2.51 132.07
Occidente_MOR_Union 22 60 1299.08 443.28 1241.5 1259.42 398.82 503 2608 2105 0.80 0.63 57.23
Occidente_QRT_Union 23 60 1908.12 574.76 1864.5 1873.08 449.97 840 3499 2659 0.54 0.35 74.20
Occidente_TEP_Union 24 60 880.67 284.71 813.5 862.71 279.47 274 1594 1320 0.49 -0.42 36.76
Occidente_ZAC_Union 25 60 642.15 200.61 648.0 632.23 197.19 203 1239 1036 0.54 0.58 25.90
Sureste_CANC_Union 26 60 1461.20 440.96 1511.0 1449.60 438.85 591 2779 2188 0.33 0.20 56.93
Sureste_CAMP_Union 27 60 535.78 171.84 557.0 539.90 199.41 126 848 722 -0.26 -0.71 22.18
Sureste_MER_Union 28 60 2085.75 634.06 2066.0 2084.00 621.95 640 3393 2753 -0.04 -0.61 81.86
Sureste_OAX_Union 29 60 846.75 309.65 783.0 815.81 235.73 380 1905 1525 1.30 2.46 39.98
Sureste_TGTZ_Union 30 60 1283.23 419.63 1244.5 1284.33 355.82 401 2357 1956 0.14 -0.10 54.17
Sureste_VER_Union 31 60 1219.13 426.36 1204.0 1193.67 454.42 248 2338 2090 0.44 -0.09 55.04
Sureste_VH_Union 32 60 940.82 380.79 931.5 921.27 297.26 111 2415 2304 1.21 3.64 49.16

Motivo se dicorció o separó

G.Divorcio <- dygraph(ts.Divorcio, main = "Se dicorció o separó", ylab = "Migrantes", xlab = "Periodo") %>%
               dyRangeSelector() %>%
                dyLegend(width = 650) %>%
                 dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
                  dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Divorcio
Analisis descriptivo: Se separó o divorció
vars n mean sd median trimmed mad min max range skew kurtosis se
Centro_ACA_Divorcio 1 60 1.28 0.60 1.28 1.25 0.51 0.00 3.56 3.56 0.71 2.06 0.08
Centro_CUER_Divorcio 2 60 1.18 0.54 1.13 1.16 0.51 0.15 2.43 2.28 0.27 -0.58 0.07
Centro_MEX_Divorcio 3 60 1.24 0.41 1.15 1.21 0.33 0.55 2.71 2.16 0.98 1.29 0.05
Centro_PACH_Divorcio 4 60 1.31 0.61 1.20 1.28 0.64 0.24 3.08 2.85 0.43 -0.21 0.08
Centro_PUE_Divorcio 5 60 1.15 0.40 1.14 1.14 0.39 0.35 2.20 1.85 0.29 -0.15 0.05
Centro_TOL_Divorcio 6 60 1.36 0.58 1.27 1.33 0.57 0.42 3.20 2.78 0.60 0.38 0.07
Centro_TLAX_Divorcio 7 60 1.11 0.47 1.08 1.09 0.43 0.14 2.17 2.04 0.44 -0.36 0.06
Noreste_DUR_Divorcio 8 60 1.30 0.52 1.21 1.29 0.47 0.13 2.53 2.40 0.27 -0.59 0.07
Noreste_MTY_Divorcio 9 60 1.29 0.43 1.30 1.28 0.43 0.42 2.89 2.46 0.54 1.41 0.06
Noreste_SLP_Divorcio 10 60 1.07 0.42 1.04 1.04 0.27 0.26 2.92 2.66 1.66 5.47 0.05
Noreste_SLT_Divorcio 11 60 1.23 0.47 1.27 1.23 0.44 0.21 2.41 2.20 0.09 -0.13 0.06
Noreste_TAM_Divorcio 12 60 1.20 0.39 1.17 1.19 0.37 0.37 2.09 1.71 0.21 -0.48 0.05
Noroeste_CHIH_Divorcio 13 60 1.44 0.53 1.50 1.43 0.51 0.33 2.89 2.55 0.21 -0.31 0.07
Noroeste_CUL_Divorcio 14 60 1.39 0.54 1.30 1.35 0.55 0.53 3.31 2.78 0.86 1.10 0.07
Noroeste_HER_Divorcio 15 60 1.51 0.62 1.47 1.50 0.71 0.26 3.02 2.76 0.11 -0.46 0.08
Noroeste_PAZ_Divorcio 16 60 1.55 0.63 1.54 1.53 0.56 0.33 3.23 2.90 0.41 0.15 0.08
Noroeste_TIJ_Divorcio 17 60 1.84 0.69 1.80 1.82 0.66 0.39 3.30 2.91 0.15 -0.57 0.09
Occidente_AGS_Divorcio 18 60 0.91 0.40 0.88 0.91 0.48 0.21 1.79 1.58 0.06 -1.00 0.05
Occidente_COL_Divorcio 19 60 1.62 0.71 1.48 1.54 0.50 0.55 4.25 3.70 1.44 2.85 0.09
Occidente_GDL_Divorcio 20 60 1.12 0.39 1.01 1.11 0.34 0.27 2.32 2.05 0.42 0.12 0.05
Occidente_LN_Divorcio 21 60 0.97 0.37 0.92 0.96 0.35 0.24 1.96 1.72 0.44 -0.22 0.05
Occidente_MOR_Divorcio 22 60 1.04 0.45 0.98 1.02 0.39 0.19 2.27 2.08 0.54 -0.14 0.06
Occidente_QRT_Divorcio 23 60 0.89 0.38 0.87 0.86 0.34 0.34 2.52 2.19 1.36 3.99 0.05
Occidente_TEP_Divorcio 24 60 1.41 0.49 1.46 1.42 0.47 0.23 2.48 2.25 -0.23 -0.31 0.06
Occidente_ZAC_Divorcio 25 60 1.05 0.41 1.03 1.05 0.41 0.00 1.95 1.95 -0.06 -0.44 0.05
Sureste_CANC_Divorcio 26 60 1.75 0.63 1.75 1.73 0.74 0.66 3.05 2.39 0.17 -1.07 0.08
Sureste_CAMP_Divorcio 27 60 1.49 0.47 1.45 1.49 0.49 0.42 2.45 2.04 0.12 -0.67 0.06
Sureste_MER_Divorcio 28 60 1.25 0.51 1.23 1.25 0.54 0.27 2.21 1.94 0.07 -0.94 0.07
Sureste_OAX_Divorcio 29 60 0.87 0.38 0.87 0.85 0.37 0.17 1.85 1.68 0.31 -0.26 0.05
Sureste_TGTZ_Divorcio 30 60 1.62 0.59 1.63 1.59 0.60 0.53 3.55 3.03 0.65 0.52 0.08
Sureste_VER_Divorcio 31 60 1.56 0.67 1.46 1.51 0.65 0.13 3.41 3.28 0.59 -0.05 0.09
Sureste_VH_Divorcio 32 60 1.72 0.63 1.63 1.67 0.56 0.70 4.32 3.62 1.26 3.22 0.08

Motivo para reunirse con un familiar

G.Familiar <- dygraph(ts.Familia, main = "Reunirse con un familiar", ylab = "Migrantes", xlab = "Periodo") %>%
               dyRangeSelector() %>%
                dyLegend(width = 650) %>%
                 dyOptions(colors = RColorBrewer::brewer.pal(32, "Set2")) %>%
                  dyHighlight(highlightSeriesOpts = list(strokeWidth = 2))
G.Familiar
Analisis descriptivo: Reunirse con un familiar
vars n mean sd median trimmed mad min max range skew kurtosis se
Centro_ACA_Familiar 1 60 7.97 2.24 7.79 7.85 1.66 2.82 15.71 12.89 0.74 1.74 0.29
Centro_CUER_Familiar 2 60 4.42 2.38 4.49 4.33 2.29 0.54 9.87 9.33 0.18 -0.69 0.31
Centro_MEX_Familiar 3 60 3.92 1.02 4.02 3.93 1.08 1.30 5.86 4.55 -0.20 -0.38 0.13
Centro_PACH_Familiar 4 60 4.08 1.49 4.22 4.09 1.09 1.08 7.66 6.58 0.01 -0.07 0.19
Centro_PUE_Familiar 5 60 3.50 0.95 3.38 3.43 0.82 1.58 6.61 5.03 0.88 1.27 0.12
Centro_TOL_Familiar 6 60 3.73 1.42 3.51 3.69 1.61 1.24 7.12 5.89 0.29 -0.65 0.18
Centro_TLAX_Familiar 7 60 3.64 1.16 3.44 3.55 1.05 1.33 6.86 5.53 0.65 0.32 0.15
Noreste_DUR_Familiar 8 60 5.50 1.75 5.11 5.38 1.75 2.21 10.57 8.36 0.58 -0.19 0.23
Noreste_MTY_Familiar 9 60 5.81 2.83 5.87 5.79 4.01 1.03 11.21 10.18 -0.01 -1.19 0.36
Noreste_SLP_Familiar 10 60 5.14 1.67 5.20 5.15 1.85 1.96 7.96 6.00 -0.03 -1.06 0.22
Noreste_SLT_Familiar 11 60 6.73 1.81 6.69 6.78 1.69 3.02 10.71 7.69 -0.14 -0.52 0.23
Noreste_TAM_Familiar 12 60 5.93 1.83 5.82 5.78 1.38 2.81 12.20 9.39 1.15 2.31 0.24
Noroeste_CHIH_Familiar 13 60 5.39 1.33 5.32 5.38 1.49 2.60 8.93 6.33 0.20 -0.31 0.17
Noroeste_CUL_Familiar 14 60 7.48 2.01 7.02 7.28 1.94 4.08 12.97 8.89 0.81 0.23 0.26
Noroeste_HER_Familiar 15 60 6.73 2.08 6.33 6.56 1.84 3.06 13.30 10.24 0.83 0.63 0.27
Noroeste_PAZ_Familiar 16 60 5.87 1.79 5.76 5.85 1.54 1.79 10.12 8.33 0.11 -0.18 0.23
Noroeste_TIJ_Familiar 17 60 8.98 2.37 9.15 9.13 2.51 3.33 13.06 9.73 -0.50 -0.61 0.31
Occidente_AGS_Familiar 18 60 3.50 1.36 3.45 3.37 1.32 1.35 8.46 7.11 1.04 1.71 0.18
Occidente_COL_Familiar 19 60 4.09 2.17 3.85 3.89 1.97 1.03 13.38 12.35 1.46 3.93 0.28
Occidente_GDL_Familiar 20 60 5.16 1.50 5.09 5.17 1.39 1.58 9.28 7.70 0.15 0.35 0.19
Occidente_LN_Familiar 21 60 3.62 1.19 3.55 3.57 1.37 1.19 6.32 5.13 0.24 -0.65 0.15
Occidente_MOR_Familiar 22 60 3.80 1.25 3.71 3.72 1.15 1.56 7.03 5.48 0.54 -0.09 0.16
Occidente_QRT_Familiar 23 60 4.28 1.46 4.18 4.27 1.45 1.42 7.78 6.36 0.12 -0.34 0.19
Occidente_TEP_Familiar 24 60 5.64 2.05 5.63 5.52 1.93 1.89 10.96 9.07 0.49 -0.21 0.26
Occidente_ZAC_Familiar 25 60 4.88 1.32 4.63 4.86 1.30 2.26 7.71 5.45 0.24 -0.75 0.17
Sureste_CANC_Familiar 26 60 7.87 2.31 7.93 7.79 2.65 3.51 14.35 10.84 0.28 -0.41 0.30
Sureste_CAMP_Familiar 27 60 6.17 1.78 5.98 6.08 1.72 2.58 10.28 7.70 0.36 -0.33 0.23
Sureste_MER_Familiar 28 60 4.56 1.57 4.36 4.48 1.60 1.21 9.50 8.29 0.62 0.95 0.20
Sureste_OAX_Familiar 29 60 4.33 1.47 4.21 4.22 1.22 1.66 10.32 8.66 1.14 2.92 0.19
Sureste_TGTZ_Familiar 30 60 6.23 1.70 6.12 6.18 1.70 2.89 11.28 8.39 0.40 0.04 0.22
Sureste_VER_Familiar 31 60 4.13 1.60 3.89 4.07 1.84 0.91 7.78 6.87 0.27 -0.55 0.21
Sureste_VH_Familiar 32 60 6.81 1.98 6.71 6.74 2.11 3.21 12.45 9.24 0.43 -0.20 0.26

Modelo jerárquico

Se utiliza la función hts() para crear una serie de tiempo jerárquica.

Donde se utilizan los datos de último nivel y se utiliza el argumento characters donde los primeros dos caracteres corresponden al primer nivel (Región), los siguientes dos corresponden al segundo nivel (Ciudades) y como último los tres caracteres corresponden al motivo de la ausencia.

  • TRA = “Trabajo”
  • EST = “Estudio”
  • UNI = “Se casó o unió”
  • DIV = “Se divorció o separó”
  • FAM = “Reunirse con un familiar”

Definición de vectores:

  • Regiones: Un vector que contiene códigos de regiones repetidos para crear una etiqueta de región específica.
  • Ciudades: Un vector que contiene códigos de ciudades que se combinan con las regiones para crear nombres únicos.
  • Motivo: Un vector que contiene el motivo de la ausencia, repetido para igualar la longitud de los otros vectores.
Regiones <- rep(c(rep("CE", 7),
                  rep("NE", 5),
                  rep("NW", 5),
                  rep("WE", 8),
                  rep("SO", 7)), 5)
Ciudades <- rep(c("11",     "24",   "01",   "32",   "04",   "14",   "29",
                  "21",     "03",   "06",   "15",   "09",
                  "08",     "19",   "20",   "30",   "18",   
                  "12",     "27",   "02",   "05",   "13",   "28",   "22",   "26",   
                  "31",     "23",   "07",   "25",   "17",   "10",   "16"), 5)

Motivo <- c(rep("TRA", 32),
            rep("EST", 32),
            rep("UNI", 32),
            rep("DIV", 32),
            rep("FAM", 32))

nombres <- paste0(Regiones, Ciudades, Motivo) #Largo de 7 | Regiones=2|Ciudades=2|Motivo=3
colnames(ts.mydata) <- nombres

nodes <- list(160, c(5, 32, 5)) #160 variables |Regiones=5|Ciudades=32|Motivos=5|  
Modelo2 <- hts(ts.mydata, nodes = nodes,characters = c(2, 2, 3))

#Cambiamos los labels 
Modelo2$labels$`Level 1` <- c("Centro", "Noreste", "Noroeste", "Sureste", "Occidente")

Nivel 1: Región

Se visualizan las series temporales agregadas de un modelo jerárquico de series temporales (Modelo1).

  • aggts(level = 1): Extrae las series temporales agregadas del nivel 1 del modelo Modelo1. El level = 1indica que se está extrayendo datos del nivel más alto en la jerarquía.
Modelo2 %>% 
 aggts(level = 1) %>%
  autoplot(size = 1) + 
   theme_classic() + 
    theme(plot.title = element_text(size = 20),
          plot.subtitle = element_text(size = 12),
          legend.text = element_text(size = 8),
          legend.key.size = unit(0.2, "cm")) +
     scale_color_viridis_d() + 
      scale_color_manual(values = RColorBrewer::brewer.pal(5, "Dark2")) + 
       scale_x_continuous(breaks = seq(2005, 2019, by = 2)) +
        labs(title = "Motivo de la ausencia 2005-2019",
             subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
             y = "Rate",
             x = "Year",
             color = "Series") 
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

Nivel 2: Cuidad autorepresentada

A continuación se muetran los datos desglosados por las 32 ciudades.

  • aggts(level = 2): indica que se están extrayendo datos de un nivel de jerarquía inferior al nivel 1.
Modelo2 %>% 
 aggts(level = 2) %>%
  autoplot(size = 0.5) + 
   theme_classic() + 
    theme(plot.title = element_text(size = 20),
          plot.subtitle = element_text(size = 12),
          legend.text = element_text(size = 8),
          legend.key.size = unit(0.5, "lines"),
          legend.position = "bottom") +
     scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(60)) + 
      guides(col = guide_legend(ncol = 15))+
       labs(title = "Motivo de la ausencia 2005-2019",
            subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
            y = "Rate",
            x = "Year",
            color = "Series") 

Si bien la gráfica anterior no permite su interpretabilidad debido a que todo el ensamble de las series están muy juntas.

Haciendo uso de la función aggts extrae las series temporales de un objeto hts para cualquier nivel de desagregación. Para aggts(Modelo1, level = 2), se especifica que queremos extraer las series temporales del nivel 2 del modelo jerárquico. Los niveles en un modelo jerárquico corresponden a diferentes niveles de agregación en la jerarquía de datos.

Para este caso, se están trabajando con dos niveles de desagregación (Regiones y Ciudades) y bien un Nivel Cero (Total).

groups <- aggts(Modelo2, level = 2)
tibble::as_tibble(groups) %>%
 tidyr::gather(Series) %>%
  mutate(Date = rep(time(groups), NCOL(groups)),
         Group =stringr::str_extract(Series, "([A-Za-z ]*)")) %>%
   ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
    geom_line() + 
     theme_classic() +
      theme(plot.title = element_text(size = 20),
            plot.subtitle = element_text(size = 12),
            axis.text.x = element_text(angle = 90, hjust = 1),
            legend.text = element_text(size = 8),
            legend.key.size = unit(0.5, "lines"),
            legend.position = "bottom") +
       scale_color_viridis_d() +
       #scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(33)) + 
        scale_x_continuous(breaks = seq(1980, 2015, by = 5)) +
         scale_y_continuous(labels = scales::comma) +
          guides(col = guide_legend(ncol = 15))+
           labs(title = "Motivo de la ausencia 2005-2019",
                subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
                y = "Rate",
                x = "Year",
                color = "Series") +
            facet_wrap(. ~ Group) 

Nivel 3: Motivo de la ausencia

Haciendo uso de la función aggts extrae las series temporales de un objeto hts para cualquier nivel de desagregación. Para aggts(Modelo2, level = 3), se especifica que queremos extraer las series temporales del nivel 23 del modelo jerárquico. Los niveles en un modelo jerárquico corresponden a diferentes niveles de agregación en la jerarquía de datos.

En modelo general, se están trabajando con tres niveles de desagregación (Motivo de ausencia, Regiones y Ciudades) y bien un Nivel Cero (Total).

groups <- aggts(Modelo2, level = 3)
#https://stringr.tidyverse.org/reference/str_locate.html
tibble::as_tibble(groups) %>%
 tidyr::gather(Series) %>% 
  mutate(Date = rep(time(groups), NCOL(groups)),
         Group =stringr::str_extract(Series, "([A-Za-z ]*)"),
         Motivo=stringr::str_sub(Series,5, 7)) %>%
   ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
    geom_line() + 
     theme_classic() +
      theme(plot.title = element_text(size = 20),
            plot.subtitle = element_text(size = 12),
            axis.text.x = element_text(angle = 90, hjust = 1),
            legend.text = element_text(size = 8),
            legend.key.width=unit(0.2, "cm"),
            legend.key.height = unit(0, "cm"),
            legend.spacing.x = unit(0, "cm"),
            legend.key.size = unit(0.5, "lines"),
            legend.position = "bottom") +
       scale_color_viridis_d() +
       #scale_color_manual(values = colorRampPalette(brewer.pal(8, "Dark2"))(160)) + 
        scale_x_continuous(breaks = seq(1980, 2015, by = 5)) +
         scale_y_continuous(labels = scales::comma) +
          guides(col = guide_legend(ncol = 15))+
           labs(title = "Motivo de la ausencia 2005-2019",
                subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
                y = "Rate",
                x = "Year",
                color = "Series") +
            facet_wrap(. ~ Group + Motivo) 

Analizando la gráfica anterior el motivo de ausencia para “Reunirse con un familiar” es la que presenta un mayor número de casos migratorios” con respecto a los otros cuatro casos.

#print(Modelo2)
#smatrix(Modelo2)
#allts(Modelo2)

Forecasting: Motivo de la ausencia en general

Se realiza un pronóstico jerárquico sobre Modelo2 para los próximos 10 periodos, utilizando el método de "middle-out" para la agregación jerárquica y el modelo ARIMA para los pronósticos individuales.

Se espera que los pronósticos sean consistentes con la estructura de agregación de las series de tiempo al agruparlas.

#h=forescast horizon
#method<-"mo", "bu", "tdfp"
f.modelo2 <- forecast(Modelo2, h = 10, method = "mo", level = 2, fmethod = "arima", parallel = TRUE, keep.fitted = TRUE)
summary(f.modelo2)

Nivel 0 al 2: Total / Región / Ciudad

Se extraen las series temporales para los niveles 0, 1 y 2 tanto del modelo de pronóstico (fcst2) como del modelo original (groups). Esto te permitirá comparar los datos originales con los pronósticos generados a diferentes niveles de la jerarquía.
- levels = 0:2: Especifica que se deben extraer las series temporales para los niveles 0, 1 y 2 del modelo jerárquico.

fcst2 <- aggts(f.modelo2, levels = 0:2)
groups <- aggts(Modelo2, levels = 0:2)
autoplot(fcst2, size = 0.5) +
 autolayer(groups) +
  geom_vline(xintercept = 2019,color = "#A8ABD7", linetype = "dashed") +
   theme_classic() +
    theme(plot.title = element_text(size = 20),
          plot.subtitle = element_text(size = 12),
          legend.text = element_text(size = 7),
          legend.key.size = unit(0.5, "lines"),
          legend.position = "bottom") +
     scale_color_viridis_d() + 
      scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
       scale_y_continuous(labels = scales::comma) +
        guides(col = guide_legend(ncol = 15))+
         labs(title = "Motivo de la ausencia 2005-2019",
              subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
              y = "Rate",
              x = "Year",
              color = "Series") 
For a multivariate time series, specify a seriesname for each time series. Defaulting to column names.

Se crea una serie temporal combinada de las series temporales originales y los pronósticos.

tabla <- ts(rbind(groups, fcst2),
                  start = start(groups), frequency = 4) #Frecuencia al año

Nivel 0: Total de casos de migración

A continuación se muetran los datos desglosados a nivel Nacional.

#http://www.sthda.com/english/wiki/ggplot2-line-types-how-to-change-line-types-of-a-graph-in-r-software
autoplot(tabla[, "Total"], colour = "#1720B7", size = 1.2, alpha = 0.6, linetype = "dashed") +      
 geom_vline(xintercept=2019.5,color = "#A8ABD7",linetype= "dashed") +
  theme_classic() +
   theme(plot.title = element_text(size = 20),
         plot.subtitle = element_text(size = 12)) + 
     scale_x_continuous(breaks = seq(2005, 2025, by = 2)) +
     labs(title = "Motivo de la ausencia 2005-2019",
          subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
          y = "Rate",
          x = "Year",
          color = "Series") 
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.

Nivel 1 a 2: Nivel región y nivel ciudad

A continuación se muetran los datos desglosados a nivel Región.

as_tibble(tabla[,-1]) %>%
 tidyr::gather(Series) %>%
  mutate(Date = rep(time(tabla), NCOL(tabla)-1),
         Group = str_extract(Series, "([A-Za-z ]*)")) %>%
   ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
    geom_line() +
     geom_vline(xintercept = 2019,color = "#A8ABD7", linetype = "dashed") +
      theme_classic() + 
       theme(plot.title = element_text(size = 20),
             plot.subtitle = element_text(size = 12),
             axis.text.x = element_text(angle = 90, hjust = 1),
             legend.text = element_text(size = 8),
             legend.key.width = unit(0.2, "cm"),
             legend.key.height = unit(0, "cm"),
             legend.spacing.x = unit(0.1, "cm"),
             legend.key.size = unit(0.5, "lines"),
             legend.position = "bottom") +
        scale_color_viridis_d() +
         scale_x_continuous(breaks = seq(2005, 2025,by = 5)) +
          guides(col = guide_legend(ncol = 15)) +
           labs(title = "Motivo de la ausencia 2005-2019",
                subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
                y = "Rate",
                x = "Year",
                color = "Series") +
            facet_wrap(. ~ Group) 

Nivel 3: Motivos de ausencia en general v

A continuación se muetran los datos desglosados por motivo de la ausencia.

fcst3 <- aggts(f.modelo2, levels = 3)
groups <- aggts(Modelo2, levels = 3)
tabla <- ts(rbind(groups, fcst3), start = start(groups), frequency = 4) #Frecuencia al año
as_tibble(tabla[,-1]) %>%
 tidyr::gather(Series) %>%
  mutate(Date = rep(time(tabla), NCOL(tabla) - 1),
         Group = str_extract(Series, "([A-Za-z ]*)"),
         Motivo = stringr::str_sub(Series, 5, 7)) %>%
   ggplot(aes(x = Date, y = value, group = Series, colour = Series)) +
    geom_line() +
     geom_vline(xintercept = 2019, color = "#A8ABD7", linetype= "dashed") +
      theme_classic() + 
       theme(plot.title = element_text(size = 20),
             plot.subtitle = element_text(size = 12),
             axis.text.x = element_text(angle=90, hjust=1),
             legend.text = element_text(size = 6),
             legend.key.width=unit(0.2, "cm"),
             legend.key.height = unit(0, "cm"),
             legend.spacing.x = unit(0.1, "cm"),
             legend.key.size = unit(0.01, "lines"),
             legend.position = "bottom") +
        scale_color_viridis_d() +
         scale_x_continuous(breaks = seq(2005, 2025,by = 5)) +
          guides(col = guide_legend(ncol = 15)) +
           labs(title = "Motivo de la ausencia 2005-2019",
                subtitle = "Trabajo / Estudio / Se casó o unió / Divorció o separó / Reunirse con un familiar",
                y = "Rate",
                x = "Year",
                color = "Series") +
            facet_wrap(.~ Group + Motivo)

Referencias

Athanasopoulos, G, Hyndman, RJ, Kourentzes, N, and Petropoulos, F (2017). Forecasting with Temporal Hierarchies. European Journal of Operational Research 262(1), 60–74.

Cochran, W.G. (1977), Sampling Techniques. Jonh Wiley and Sons, New York.

Encuesta Nacional de Ocupación y Empleo (ENOE), población de 15 años y más de edad. (2020). 50 preguntas y respuestas. Instituto Nacional de Estadística Geografía e Informática. Retrieved May 7, 2020, from https://www.inegi.org.mx/programas/enoe/15ymas/default.html#Documentacion

Forecasting Hierarchical Time Series using R - Brillio Data Science - Medium. (n.d.). Retrieved March 30, 2020, from https://medium.com/brillio-data-science/forecasting-hierarchical-time-series-using-r-598828dba435

R. J. Hyndman and A. Koehler (2006), Another look at measures of forecast accuracy, International Journal of Forecasting, 22, 679-688.

Hyndman R.J., Ahmed R.A., Athanasopoulos G., Shang H.L., (2011), Optimal combination forecasts for hierarchical time series, Computational Statistics & Data Analysis 55(9), 2579 -2589.

Hyndman, R. J., Athanasopoulos, G., & Shang, H. L. (2014). hts: An R Package for Forecasting Hierarchical or Grouped Time Series. https://cran.r-project.org/web/packages/hts/vignettes/hts.pdf?forcedefault=true

Hyndman, RJ (2017). forecast: Forecasting Functions for Time Series and Linear Models. R package version 8.1. http://pkg.robjhyndman.com/forecast.

Librerías

Librerías que se usaron en el trabajo

 [1] "purrr"        "psych"        "RColorBrewer" "tidyr"        "tibble"       "stringr"     
 [7] "htmlwidgets"  "webshot"      "ggpubr"       "ggplot2"      "knitr"        "kableExtra"  
[13] "dplyr"        "openxlsx"     "data.table"   "hts"          "forecast"     "dygraphs"    
[19] "extrafont"    "showtext"     "showtextdb"   "sysfonts"    

Nos ha servido a construir modelos de series de tiempo con datos estructurales para fines de pronósticos.

Creative Commons Licence
This work by [Diana Villasana Ocampo]{xmlns:cc= “http://creativecommons.org/ns#” property = “cc:attributionName”} is licensed under a Creative Commons Attribution 4.0 International License.


  1. (https://www.inegi.org.mx/programas/enoe/15ymas/)↩︎

  2. (Forecasting Hierarchical Time Series using R - Brillio Data Science - Medium. (n.d.). Retrieved March 31, 2020, from https://medium.com/brillio-data-science/forecasting-hierarchical-time-series-using-r-598828dba435)↩︎

LS0tDQp0aXRsZTogIkhpZXJhcmNoaWNhbCBUaW1lIFNlcmllcyINCnN1YnRpdGxlOiAiRW5jdWVzdGEgZGUgTmFjaW9uYWwgZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoRU5PRSkiDQphdXRob3I6ICJEaWFuYSBWaWxsYXNhbmEgT2NhbXBvIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGNzczogInN0eWxlc3MuY3NzIg0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICB0aGVtZTogZmxhdGx5DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiB0cnVlDQotLS0NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRSwgY2FjaGUubGF6eSA9IEZBTFNFLCBjb2xsYXBzZSA9IFRSVUUsIA0KICAgICAgICAgICAgICAgICAgICAgICNjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIiwNCiAgICAgICAgICAgICAgICAgICAgICBldmFsID0gVFJVRQ0KICAgICAgICAgICAgICAgICAgICAgICkNCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gcnByb2pyb290OjpmaW5kX3JzdHVkaW9fcm9vdF9maWxlKCkpDQpzZXR3ZChoZXJlOjpoZXJlKCkpDQpgYGANCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgcmVzdWx0cz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiNGb250IFN0bHllDQpyZXF1aXJlKHNob3d0ZXh0KQ0KbGlicmFyeShleHRyYWZvbnQpDQp3aW5kb3dzRm9udHMoKQ0KYGBgDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHJlc3VsdHM9RkFMU0UsIGV2YWwgPSBUUlVFfQ0KIyBMaWJyZXLDrWFzIGVuIGVsIGRvY3VtZW50bw0KcmVxdWlyZShkeWdyYXBocykNCnJlcXVpcmUoaHRzKQ0KcmVxdWlyZShkYXRhLnRhYmxlKQ0KcmVxdWlyZShvcGVueGxzeCkNCnJlcXVpcmUoZHBseXIpDQpyZXF1aXJlKGthYmxlRXh0cmEpDQpyZXF1aXJlKGtuaXRyKQ0KcmVxdWlyZShnZ3B1YnIpDQpyZXF1aXJlKGdncGxvdDIpDQpyZXF1aXJlKHdlYnNob3QpDQpyZXF1aXJlKGh0bWx3aWRnZXRzKQ0KcmVxdWlyZShzdHJpbmdyKQ0KcmVxdWlyZSh0aWJibGUpDQpyZXF1aXJlKHRpZHlyKQ0KcmVxdWlyZShSQ29sb3JCcmV3ZXIpDQpyZXF1aXJlKHBzeWNoKQ0KbGlicmFyeShwdXJycikNCmBgYA0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHJlc3VsdHM9J2FzaXMnLCBldmFsPShvcHRzX2tuaXQkZ2V0KCdybWFya2Rvd24ucGFuZG9jLnRvJykgPT0gJ2xhdGV4Jyl9DQpjYXQoJ1xccGFnZWJyZWFrJykNCmBgYA0KDQoNCiMgSW50cm9kdWNjacOzbiAgIA0KDQpFbCBtw6l0b2RvIGRlIHNlcmllcyB0ZW1wb3JhbGVzIGplcsOhcnF1aWNhcyBlcyB1bmEgdMOpY25pY2EgYXZhbnphZGEgdXRpbGl6YWRhIHBhcmEgbW9kZWxhciB5IHByZWRlY2lyIGRhdG9zIHRlbXBvcmFsZXMgcXVlIGV4aGliZW4gdW5hIGVzdHJ1Y3R1cmEgamVyw6FycXVpY2EgbmF0dXJhbC4gIFN1IGFwbGljYWNpw7NuIGVmaWNheiBwdWVkZSBtZWpvcmFyIHNpZ25pZmljYXRpdmFtZW50ZSBsYSBwcmVjaXNpw7NuIGRlIGxvcyBwcm9uw7NzdGljb3MgeSBmYWNpbGl0YXIgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGVzdHJhdMOpZ2ljYXMgZW4gZGl2ZXJzYXMgw6FyZWFzIGRlIGFwbGljYWNpw7NuLCBlcyBlc3BlY2lhbG1lbnRlIMO6dGlsIGVuIHNpdHVhY2lvbmVzIGRvbmRlIGxvcyBkYXRvcyBzZSBwdWVkZW4gZGVzY29tcG9uZXIgZW4gbcO6bHRpcGxlcyBuaXZlbGVzIGRlIGFncmVnYWNpw7NuLCBjb21vIHBvciBlamVtcGxvLCBkZXNwbGF6YW1pZW50b3MgaW50ZXJub3MsIHJlZ2lvbmVzIHkgcGHDrXMuICAgDQoNCg0KKipDb21wb25lbnRlcyBQcmluY2lwYWxlcyoqICAgDQoNCjEuICoqRGVzY29tcG9zaWNpw7NuIEplcsOhcnF1aWNhKio6IERpdmlkZSBsb3MgZGF0b3MgZW4gbcO6bHRpcGxlcyBzZXJpZXMgdGVtcG9yYWxlcyBpbnRlcnJlbGFjaW9uYWRhcyBxdWUgc2Ugb3JnYW5pemFuIGVuIHVuYSBlc3RydWN0dXJhIGRlIMOhcmJvbCBqZXLDoXJxdWljby4gUG9yIGVqZW1wbG8sIGxvcyBkZXNwbGF6YW1pZW50b3MgaW50ZXJub3MgcHVlZGVuIGRlc2NvbXBvbmVyc2UgZW4gZGVzcGxhemFtaWVudG9zIGludGVybm9zIHBvciByZWdpw7NuLCB5IGEgc3UgdmV6LCBsb3MgZGVzcGxhemFtaWVudG9zIGludGVybm9zIHBvciByZWdpw7NuIHNlIGRlc2NvbXBvbmVuIHBvciBlc3RhZG9zLiAgICAgICANCg0KMi4gKipNb2RlbGFkbyBJbmRlcGVuZGllbnRlIHkgQ29uc2lzdGVudGUqKjogQ2FkYSBzZXJpZSB0ZW1wb3JhbCBkZW50cm8gZGUgbGEgamVyYXJxdcOtYSBzZSBtb2RlbGEgZGUgZm9ybWEgaW5kZXBlbmRpZW50ZSB1dGlsaXphbmRvIG3DqXRvZG9zIGRlIHNlcmllcyB0ZW1wb3JhbGVzIHRyYWRpY2lvbmFsZXMgY29tbyBBUklNQSBvIG3DqXRvZG9zIG3DoXMgYXZhbnphZG9zIGNvbW8gbW9kZWxvcyBkZSBlc3BhY2lvIGRlIGVzdGFkby4gICANCg0KMy4gKipDb25zaXN0ZW5jaWEgQWdyZWdhZGEqKjogTG9zIHByb27Ds3N0aWNvcyBkZSBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgaW5kaXZpZHVhbGVzIHNlIGFncmVnYW4gZGUgbWFuZXJhIGNvaGVyZW50ZSBwYXJhIGdlbmVyYXIgcHJvbsOzc3RpY29zIHByZWNpc29zIHkgY29uc2lzdGVudGVzIGVuIHRvZG9zIGxvcyBuaXZlbGVzIGRlIGxhIGplcmFycXXDrWEuICAgDQoNCioqQ29uc2lkZXJhY2lvbmVzIFByw6FjdGljYXMqKg0KDQotICoqU29mdHdhcmUgRXNwZWNpYWxpemFkbyoqOiBVdGlsaXphY2nDs24gZGUgaGVycmFtaWVudGFzIGNvbW8gYFJgIChjb24gcGFxdWV0ZXMgY29tbyBgaHRzYCkgbyBgUHl0aG9uYCBwYXJhIGltcGxlbWVudGFyIHkgYXV0b21hdGl6YXIgZWwgbcOpdG9kby4gICAgDQotICoqVmFsaWRhY2nDs24geSBBanVzdGUqKjogVmFsaWRhciBsb3MgbW9kZWxvcyBlbiBtw7psdGlwbGVzIG5pdmVsZXMgZGUgbGEgamVyYXJxdcOtYSB5IGFqdXN0YXIgc2Vnw7puIHNlYSBuZWNlc2FyaW8gcGFyYSBtZWpvcmFyIGxhIHByZWNpc2nDs24uICAgICANCg0KDQojIEVuY3Vlc3RhIE5hY2lvbmFsIGRlIE9jdXBhY2nDs24geSBFbXBsZW8gKGBFTk9FYCkgICAgICANCg0KTGEgRW5jdWVzdGEgTmFjaW9uYWwgZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoYEVOT0VgKSwgcmVhbGl6YWRhIHBvciBlbCBJbnN0aXR1dG8gTmFjaW9uYWwgZGUgRXN0YWTDrXN0aWNhIHkgR2VvZ3JhZsOtYSAoYElORUdJYCksIGVzIHVuYSBoZXJyYW1pZW50YSBlc2VuY2lhbCBwYXJhIG1lZGlyIGxhIGRpbsOhbWljYSBkZWwgbWVyY2FkbyBsYWJvcmFsIGVuIE3DqXhpY28uIFByb3BvcmNpb25hIGRhdG9zIGRldGFsbGFkb3Mgc29icmUgbGEgb2N1cGFjacOzbiwgZWwgZW1wbGVvLCBlbCBkZXNlbXBsZW8geSBvdHJhcyBjYXJhY3RlcsOtc3RpY2FzIHJlbGV2YW50ZXMgZGUgbGEgcG9ibGFjacOzbiBlY29uw7NtaWNhbWVudGUgYWN0aXZhLiAgDQoNCioqT2JqZXRpdm9zIFByaW5jaXBhbGVzKiogIA0KDQoxLiAqKk1lZGljacOzbiBkZSBsYSBQb2JsYWNpw7NuIEVjb27Ds21pY2FtZW50ZSBBY3RpdmEgKFBFQSkqKjogSWRlbnRpZmljYXIgbGEgcHJvcG9yY2nDs24gZGUgbGEgcG9ibGFjacOzbiBxdWUgcGFydGljaXBhIGVuIGVsIG1lcmNhZG8gbGFib3JhbCwgaW5jbHV5ZW5kbyB0YW50byBhIGxhcyBwZXJzb25hcyBvY3VwYWRhcyBjb21vIGEgbGFzIGRlc29jdXBhZGFzLiAgDQoNCjIuICoqQW7DoWxpc2lzIGRlbCBFbXBsZW8qKjogUHJvcG9yY2lvbmFyIGluZm9ybWFjacOzbiBzb2JyZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZWwgZW1wbGVvLCBpbmNsdXllbmRvIGxhIG5hdHVyYWxlemEgZGVsIHRyYWJham8sIGxhcyBjb25kaWNpb25lcyBsYWJvcmFsZXMsIGxvcyBzZWN0b3JlcyBlY29uw7NtaWNvcyB5IGxhcyB0YXNhcyBkZSBlbXBsZW8gZm9ybWFsIGUgaW5mb3JtYWwuICAgDQoNCjMuICoqRXZhbHVhY2nDs24gZGVsIERlc2VtcGxlbyoqOiBFc3RpbWFyIGxhIHRhc2EgZGUgZGVzZW1wbGVvIHkgYW5hbGl6YXIgbGFzIGNhcmFjdGVyw61zdGljYXMgZGUgbGEgcG9ibGFjacOzbiBkZXNvY3VwYWRhLCBpbmNsdXllbmRvIGxhIGR1cmFjacOzbiBkZWwgZGVzZW1wbGVvIHkgbG9zIGVzZnVlcnpvcyBkZSBiw7pzcXVlZGEgZGUgZW1wbGVvLiAgIA0KDQo0LiAqKkluZm9ybWFjacOzbiBTb2Npb2Vjb27Ds21pY2EqKjogUmVjb3BpbGFyIGRhdG9zIHNvYnJlIGxhIGVkdWNhY2nDs24sIGxvcyBpbmdyZXNvcyB5IG90cmFzIHZhcmlhYmxlcyBzb2Npb2Vjb27Ds21pY2FzIHF1ZSBhZmVjdGFuIHkgc29uIGFmZWN0YWRhcyBwb3IgZWwgZW1wbGVvIHkgZWwgZGVzZW1wbGVvLiAgDQogDQoqKkNvbXBvbmVudGVzIFByaW5jaXBhbGVzKiogICAgDQoNCi0gKipFbmN1ZXN0YXMgVHJpbWVzdHJhbGVzKio6IExhIEVOT0Ugc2UgcmVhbGl6YSBkZSBtYW5lcmEgY29udGludWEsIGNvbiByZXN1bHRhZG9zIHB1YmxpY2Fkb3MgdHJpbWVzdHJhbG1lbnRlLCBsbyBxdWUgcGVybWl0ZSB1biBzZWd1aW1pZW50byBjZXJjYW5vIGRlIGxhcyB0ZW5kZW5jaWFzIGxhYm9yYWxlcy4gICANCi0gKipDb2JlcnR1cmEgTmFjaW9uYWwqKjogTGEgZW5jdWVzdGEgYWJhcmNhIHRvZGFzIGxhcyBlbnRpZGFkZXMgZmVkZXJhdGl2YXMgZGUgTcOpeGljbywgb2ZyZWNpZW5kbyB1bmEgdmlzacOzbiBjb21wcmVuc2l2YSB5IGRldGFsbGFkYSBkZWwgbWVyY2FkbyBsYWJvcmFsIGEgbml2ZWwgbmFjaW9uYWwgeSByZWdpb25hbC4gICAgDQotICoqQW1wbGl0dWQgZGUgVGVtYXMqKjogSW5jbHV5ZSBpbmZvcm1hY2nDs24gc29icmUgZW1wbGVvIGZvcm1hbCBlIGluZm9ybWFsLCBzdWJlbXBsZW8sIG9jdXBhY2lvbmVzLCBpbmdyZXNvcywgY29uZGljaW9uZXMgZGUgdHJhYmFqbyB5IG3DoXMuICAgIA0KDQoqKkFwbGljYWNpb25lcyoqICAgIA0KDQotIGBQb2zDrXRpY2FzIFDDumJsaWNhc2A6IExvcyBkYXRvcyBkZSBsYSBFTk9FIHNvbiBjcnVjaWFsZXMgcGFyYSBsYSBmb3JtdWxhY2nDs24geSBldmFsdWFjacOzbiBkZSBwb2zDrXRpY2FzIGxhYm9yYWxlcywgZWR1Y2F0aXZhcyB5IGVjb27Ds21pY2FzLiAgIA0KLSBgSW52ZXN0aWdhY2nDs24gQWNhZMOpbWljYWA6IFByb3BvcmNpb25hIHVuYSBiYXNlIGRlIGRhdG9zIHJpY2EgcGFyYSBlc3R1ZGlvcyBzb2JyZSBlbCBtZXJjYWRvIGxhYm9yYWwsIGxhIGVjb25vbcOtYSBkZWwgdHJhYmFqbyB5IGxhIHNvY2lvbG9nw61hIGRlbCBlbXBsZW8uICAgDQotIGBBbsOhbGlzaXMgU2VjdG9yaWFsYDogQXl1ZGEgYSBpZGVudGlmaWNhciB0ZW5kZW5jaWFzIHkgZGVzYWbDrW9zIGVzcGVjw61maWNvcyBlbiBkaXN0aW50b3Mgc2VjdG9yZXMgZWNvbsOzbWljb3MsIGluZm9ybWFuZG8gZGVjaXNpb25lcyBlbXByZXNhcmlhbGVzIHkgZ3ViZXJuYW1lbnRhbGVzLiAgIA0KDQoqKkNvbnNpZGVyYWNpb25lcyBQcsOhY3RpY2FzKiogICAgDQoNCi0gKipBY2Nlc28gYSBEYXRvcyoqOiBMb3MgZGF0b3MgZGUgbGEgRU5PRSBlc3TDoW4gZGlzcG9uaWJsZXMgcMO6YmxpY2FtZW50ZSBhIHRyYXbDqXMgZGVsIElORUdJLCBmYWNpbGl0YW5kbyBzdSB1c28gcGFyYSBhbsOhbGlzaXMgeSBlc3R1ZGlvcyBkZXRhbGxhZG9zLg0KLSAqKk1ldG9kb2xvZ8OtYSBSaWd1cm9zYSoqOiBMYSBlbmN1ZXN0YSBzaWd1ZSBlc3TDoW5kYXJlcyBtZXRvZG9sw7NnaWNvcyBlc3RyaWN0b3MsIGFzZWd1cmFuZG8gbGEgY2FsaWRhZCB5IGNvbmZpYWJpbGlkYWQgZGUgbG9zIGRhdG9zLg0KLSAqKkFjdHVhbGl6YWNpw7NuIENvbnRpbnVhKio6IExhIEVOT0Ugc2UgYWN0dWFsaXphIGNvbnRpbnVhbWVudGUsIHBlcm1pdGllbmRvIHVuIG1vbml0b3JlbyBwcmVjaXNvIGRlIGxhcyBkaW7DoW1pY2FzIGxhYm9yYWxlcyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8uICAgIA0KDQojIyBEaXNlw7FvIGNvbmNlcHR1YWwgDQoNCkxhIHBvYmxhY2nDs24gb2JqZXRpdm8gZGUgbGEgZW5jdWVzdGEgZXN0w6EgY29uZm9ybWFkYSBwb3IgdG9kb3MgbG9zIHF1ZSByZXNpZGVuIGhhYml0dWFsbWVudGUgbGFzIHZpdmllbmRhcyBzZWxlY2Npb25hZGFzLiBMb3MgaW5zdHJ1bWVudG9zIGRlIGNhcHRhY2nDs24gbcOhcyBpbXBvcnRhbnRlcyBzb24gZWwgYEN1ZXN0aW9uYXJpbyBTb2Npb2RlbW9ncsOhZmljbyAoQ1MpYCB5IGVsIGBDdWVzdGlvbmFyaW8gZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoQ09FKWAuIExhIGluZm9ybWFjacOzbiByZWZlcmVudGUgYSBsb3MgaG9nYXJlcyB5IGEgbGFzIGNhcmFjdGVyw61zdGljYXMgc29jaW9kZW1vZ3LDoWZpY2FzIGRlIGxvcyByZXNpZGVudGVzIGRlIGxhIHZpdmllbmRhIHNlIHJlZ2lzdHJhIGVuIGVsIGBDU2AsIG1pZW50cmFzIHF1ZSBlbCBgQ09FYCBjb250aWVuZSB2YXJpYWJsZXMgcXVlIGlkZW50aWZpY2FuIGVuIHByaW1lciBsdWdhciBsYSBjb25kaWNpw7NuIGRlIGFjdGl2aWRhZCB5IGVuIHNlZ3VuZG8gdMOpcm1pbm8gcHJlZ3VudGFzIGVzcGVjw61maWNhcyBwYXJhIGNhZGEgdW5vIGRlIGxvcyB1bml2ZXJzb3MuIEVzIG5lY2VzYXJpbyBtZW5jaW9uYXIgcXVlIGVsIGBDT0VgIHNlIGxldmFudGEgYSBsYSBwb2JsYWNpw7NuIGRlIDEyIGHDsW9zIGVuIGFkZWxhbnRlLCBzaW4gZW1iYXJnbywgcG9yIGN1ZXN0aW9uZXMgbWV0b2RvbMOzZ2ljYXMgZGVsIG1hcmNvIGRlIGxhIE9DREUgc2UgcMO6YmxpY2EgcGFyYSBsYSBwb2JsYWNpw7NuIGRlIDE1IGHDsW9zIGVuIGFkZWxhbnRlLiAgICAgICAgDQoNCiMjIERpc2XDsW8gdGVtcG9yYWwgDQoNCkxhIGBFTk9FYCBlcyB1bmEgZW5jdWVzdGEgcGFuZWwgZGUgcm90YXRvcmlvLCBlcyBkZWNpciwgdGllbmUgdW5hIG11ZXN0cmEgZGUgdml2aWVuZGFzIGRpdmlkaWRhIGVuIDUgcGFuZWxlcyBkZSByb3RhY2nDs24uIERlIGxvcyBjdWFsZXMsIHJvdGEgdW5vIGNhZGEgdHJpbWVzdHJlOyBjb25zZXJ2YW5kbyBkZSBlc3RhIG1hbmVyYSwgZWwgODAgcG9yIGNpZW50byBkZSBsYSBtdWVzdHJhIGVudHJlIGRvcyB0cmltZXN0cmVzIGNvbnNlY3V0aXZvcy4gIExvIHF1ZSBwZXJtaXRlIGxsZXZhciBhIGNhYm8gZG9zIGltcG9ydGFudGVzIGFjdGl2aWRhZGVzOiBzdXN0aXR1aXIgZWwgbWFyY28gbXVlc3RyYWwgeSBjYW1iaWFyIGVzcXVlbWEgZGUgbXVlc3RyZW8uICAgICANCg0KUG9yIG90cmEgcGFydGUsIHRvZGEgbGEgY2FudGlkYWQgZGUgaW5mb3JtYWNpw7NuIHJlY2FiYWRhIGRlIGxhIG1pc21hIHVuaWRhZCBkZSBtdWVzdHJlbyBlbiBkb3MgbyBtw6FzIHBlcmlvZG9zIGNvbnNlY3V0aXZvcyBwZXJtaXRpcsOhIHRlw7NyaWNhbWVudGUgaW5jcmVtZW50YXIgbGEgcHJlY2lzacOzbiBkZSBsYXMgZXN0aW1hY2lvbmVzLCBwcmluY2lwYWxtZW50ZSBkZWwgY2FtYmlvIGVuIGVsbGFzLiAgQ29jaHJhbiAoMTk3NykgY29pbmNpZGUgY29uIGVzdG8geSBhZGVtw6FzIGVzdGFibGVjZSBxdWUsIGVuIGxhIG9idGVuY2nDs24gZGUgbGFzIGVzdGltYWNpb25lcyBhY3R1YWxlcywgc2UgZ2FuYSBsYSBtaXNtYSBwcmVjaXNpw7NuIHNpIHNlIGNvbnNlcnZhIGxhIG11ZXN0cmEgaW5pY2lhbCBvIHNlIGNhbWJpYSBlbiBjYWRhIG9jYXNpw7NuLiAgICANCg0KIyMgQ29uZGljacOzbiBkZSBSZXNpZGVuY2lhDQoNClVuIGFzcGVjdG8gcmVsZXZhbnRlIHBvciBjb25zaWRlcmFyIGZ1ZSBpZGVudGlmaWNhciBsYSBjb25kaWNpw7NuIGRlIHJlc2lkZW5jaWEsIGEgcXVpZW5lcyBkZSBsb3MgcmVzaWRlbnRlcyBjb250aW51YWJhbiB2aXZpZW5kbyBlbiBlbCBob2dhciBvIGVuIG90cm9zIHTDqXJtaW5vcyBhIHF1aWVuZXMgbm8gaGFuIGVzdGFkbyBlbiB1biBwcm9jZXNvIGRlIHRyYW5zaWNpw7NuIGRlIHJlc2lkZW5jaWEsIGFzw60gY29tbyBsb3MgYXVzZW50ZXMgZGVmaW5pdGl2b3MgeSBhIGxvcyBudWV2b3MgcmVzaWRlbnRlcy4gQWwgcmVzcGVjdG8sIGNhYmUgYWNvdGFyLCBxdWUgZWwgZGlzZcOxbyBjb25jZXB0dWFsIGRlbCBDdWVzdGlvbmFyaW8gU29jaW9kZW1vZ3LDoWZpY28gaWRlbnRpZmljYSBhIHF1aWVuZXMgeWEgbm8gc2UgZW5jdWVudHJhbiBwb3IgaGFiZXIgcGFydGlkbyBhIG90cm8gbHVnYXIgcG9yIGRpdmVyc2FzIGNhdXNhcyBlbnRyZSDDqXN0YXMgcG9yIG1vcnRhbGlkYWQgKGBBdXNlbnRlcyBEZWZpbml0aXZvc2ApIHkgZGlzdGluZ3VlIHF1aWVuZXMgc29uIG51ZXZvcyBlbiBsbyBkZWwgbWlzbW8gaG9nYXIgcG9yIGhhYmVyIGFycmliYWRvIGRlIGFsZ8O6biBsdWdhciBvdHJvIGx1Z2FyIHBvciBkaXZlcnNhcyBjYXVzYXMgZW50cmUgZWxsYXMgZWwgbmFjaW1pZW50byAoYE51ZXZvIFJlc2lkZW50ZXNgKS4gICAgICAgDQoNCg0KIyMgTW90aXZvIGRlIGxhIG1pZ3JhY2nDs24gW14xXSAgIA0KDQpbXjFdOihodHRwczovL3d3dy5pbmVnaS5vcmcubXgvcHJvZ3JhbWFzL2Vub2UvMTV5bWFzLykgIA0KDQpMb3MgZGF0b3Mgc29uIHJlY29waWxhZG9zIGRlIGxhIGBFTk9FYCwgc2llbmRvLCBsYSBmdWVudGUgcHJpbmNpcGFsIGRlIGluZm9ybWFjacOzbiBzb2JyZSBlbCBtZXJjYWRvIGxhYm9yYWwgbWV4aWNhbm8gYWwgb2ZyZWNlciBkYXRvcyBkZSBtYW5lcmEgdHJpbWVzdHJhbCBkZSBsYSBmdWVyemEgZGUgdHJhYmFqbywgb2N1cGFjacOzbiwgbGEgaW5mb3JtYWxpZGFkIGxhYm9yYWwsIGxhIHN1Ym9jdXBhY2nDs24geSBkZXNvY3VwYWNpw7NuLiAgIA0KDQpMYSBFTk9FIGluaWNpYSBzdSBsZXZhbnRhbWllbnRvIGVuIDIwMDUgeSBzZSByZXBpdGUgZW4gaW50ZXJ2YWxvcyByZWd1bGFyZXMgZGUgdGllbXBvLCBjYXB0YW5kbyBsYSBpbmZvcm1hY2nDs24gYSBuaXZlbCBuYWNpb25hbC4gRXN0ZSB0aXBvIGRlIGVuY3Vlc3RhIHBlcm1pdGUgY2FwdGFyIHkgY29ub2NlciBkZSBtZWpvciBtYW5lcmEgbGFzIGNhcmFjdGVyw61zdGljYXMgc29jaW9lY29uw7NtaWNhcyBkZSBsYSBwb2JsYWNpw7NuIG1leGljYW5hIGRlIDE1IGHDsW9zIHkgbcOhcy4gICANCg0KRWwgb2JqZXRpdm8gZGVsIHRyYWJham8gZXMgaW1wbGVtZW50YXIgeSBjb21wYXJhciBsYXMgIGRpZmVyZW50ZXMgc2VyaWVzIGRlIHRpZW1wbyBkZSBtYW5lcmEgamVyw6FycXVpY2EgeSBwZXJtaXRpciBlbCBkZXNnbG9zZSBkZSBsYXMgY2F1c2FzIGRlIG1pZ3JhY2nDs24uICAgICAgDQoNCiMjIEluZGljYWRvcmVzIA0KDQpUb21hbmRvIGxhcyBwcmVndW50YXMgZGVsIGN1ZXN0aW9uYXJpbyBkZSBsYXMgY3VhbGVzIHNvbiBtw6FzIGRlICp0cmVzY2llbnRhcyBiYXNlcyBkZSBkYXRvcyogY29uICoxNTAgbWlsIGNhc29zKiBhIG5pdmVsIG5hY2lvbmFsIGVuIGxvcyBkaWZlcmVudGVzIHBlcmlvZG9zIGRlIHRpZW1wby4gICAgICANCg0KTGFzIGNvYmVydHVyYXMgZ2VvZ3LDoWZpY2FzIG8gZG9taW5pb3MgZGUgZXN0dWRpbyBwYXJhIGxhcyBjdWFsZXMgc2UgZ2VuZXJhbiBlc3RpbWFjaW9uZXMgc29uOiAgICANCg0KLQlgQ2l1ZGFkIEF1dG9yZXByZXNlbnRhZGFgICAgDQotCWBFbnRpZGFkIEZlZGVyYXRpdmFgICAgDQotCWBOYWNpb25hbGAgICANCg0KU2UgdG9tYSBjb21vIHJlZmVyZW5jaWEgbGEgcHJlZ3VudGEgYGNzX2FkX21vdGAgKipNb3Rpdm8gZGUgbGEgbWlncmFjacOzbiAqKiwgZW4gbGEgY3VhbCBzZSBkZXNnbG9zYSBlbiBsYXMgc2lndWllbnRlcyBjYXRlZ29yw61hcy4gICANCg0KLSBUcmFiYWpvICAgICANCi0gRXN0dWRpbyAgIA0KLSBTZSBjYXPDsyBvIHVuacOzICAgICANCi0gU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyAgICANCi0gUHJvYmxlbWFzIGRlIHNhbHVkICAgDQotIFJldW5pcnNlIGNvbiBsYSBmYW1pbGlhICAgICAgICAgICANCi0gSW5zZWd1cmlkYWQgcMO6YmxpY2EgICAgICANCi0gRmFsbGVjacOzICAgICAgIA0KLSBPdHJvIE1vdGl2byAgICAgICANCi0gTm8gc2FiZSAgDQoNCkRlIGxhcyBjdWFsZXMgc29sbyBzZSB0b21hbiA1IGNhc29zIHBhcmEgZWwgcHJvcMOzc2l0byBkZWwgcHJlc2VudGUgdHJhYmFqby4gICANCg0KKipCYXNlIGRlIGRhdG9zKiogICANCg0KU2UgY2FyZ2FuIGxhcyBiYXNlcyBkZSBkYXRvcyBxdWUgY29udGllbmVuIGxvcyBjaW5jbyBwcmluY2lwYWxlcyBtb3Rpdm9zIGRlIGxhIG1pZ3JhY2nDs24sIHRvbWFuZG8gY29tbyByZWZlcmVuY2lhIGxvcyBkYXRvcyBkZWwgMjAwNSBhbCAyMDE5LiAgIA0KDQotIGAoZGV0ZWN0RGF0ZXMgPSBUUlVFKWA7IGxhcyBmZWNoYXMgc2UgZGV0ZWN0YW4geSBzZSBjb252aWVydGVuIGF1dG9tw6F0aWNhbWVudGUgZW4gb2JqZXRvcyBkZSBmZWNoYSBlbiBSLiAgDQoNCmBgYHtyfQ0KVC5UcmFiYWpvIDwtIHJlYWQueGxzeChwYXN0ZTAoaGVyZTo6aGVyZSgpLCAiL0Jhc2UgZGUgZGF0b3MvUmVzdWx0YWRvcyBFTk9FLnhsc3giKSwNCiAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiVHJhYmFqbyIsIA0KICAgICAgICAgICAgICAgICAgICAgICBjb2xOYW1lcyA9IFRSVUUsIGRldGVjdERhdGVzID0gVFJVRSkNClQuRXN0dWRpbyA8LSByZWFkLnhsc3gocGFzdGUwKGhlcmU6OmhlcmUoKSwgIi9CYXNlIGRlIGRhdG9zL1Jlc3VsdGFkb3MgRU5PRS54bHN4IiksIA0KICAgICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJFc3R1ZGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgY29sTmFtZXMgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgZGV0ZWN0RGF0ZXMgPSBUUlVFKQ0KVC5VbmlvbiA8LSByZWFkLnhsc3gocGFzdGUwKGhlcmU6OmhlcmUoKSwgIi9CYXNlIGRlIGRhdG9zL1Jlc3VsdGFkb3MgRU5PRS54bHN4IiksDQogICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJVbmlvbiIsDQogICAgICAgICAgICAgICAgICAgICBjb2xOYW1lcyA9IFRSVUUsIA0KICAgICAgICAgICAgICAgICAgICAgZGV0ZWN0RGF0ZXMgPSBUUlVFKQ0KVC5EaXZvcmNpbyA8LSByZWFkLnhsc3gocGFzdGUwKGhlcmU6OmhlcmUoKSwgIi9CYXNlIGRlIGRhdG9zL1Jlc3VsdGFkb3MgRU5PRS54bHN4IiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiRGl2b3JjaW8iLCANCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbE5hbWVzID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlY3REYXRlcyA9IFRSVUUpDQpULkZhbWlsaWEgPC0gcmVhZC54bHN4KHBhc3RlMChoZXJlOjpoZXJlKCksICIvQmFzZSBkZSBkYXRvcy9SZXN1bHRhZG9zIEVOT0UueGxzeCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiwgDQogICAgICAgICAgICAgICAgICAgICAgIGNvbE5hbWVzID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgIGRldGVjdERhdGVzID0gVFJVRSkNCmBgYA0KDQoNClNlIGRpdmlkZSBlbnRyZSBsYSBwb2JsYWNpw7NuLCBkZWJpZG8gYSBxdWUgc2kgdG9tYW4gbG9zIGFic29sdXRvcyBkZSBsYXMgcGVyc29uYXMgcXVlIGNhbWJpYXJvbiBkZSByZXNpZGVuY2lhIHBvciBhbGd1bm8gZGUgbG9zIGRpZmVyZW50ZXMgbW90aXZvcyBkZSBhdXNlbmNpYS4gIEVzdG9zIHRpZW5kZW4gYSBzZXIgbWF5b3JlcyBlbiBhbGd1bmFzIGNpdWRhZGVzLCBkZWJpZG8gc2UgdGllbmUgbWF5b3IgZGVuc2lkYWQgZGUgcG9ibGFjacOzbi4gIFBlcm1pdGllbmRvIGFzw60gbGEgY29tcGFyYWJpbGlkYWQgZW50cmUgY2l1ZGFkZXMgcG9yIHVuYSByYXrDs24gZGUgY2FkYSAxMDAwIHBlcnNvbmFzLiAgIA0KDQpTZSBkZWZpbmUgbGEgZnVuY2nDs24gbGxhbWFkYSBgZGl2aWRlX2NvbHVtbnNgIHF1ZSB0b21hIGRvcyBkYXRhLmZyYW1lcyAoYGRmMWAgeSBgZGYyYCkuIExhIGZ1bmNpw7NuOiAgIA0KDQotIEV4dHJhZSB0b2RhcyBsYXMgY29sdW1uYXMgZGUgZGYxIHkgZGYyIGRlc2RlIGxhIHNlZ3VuZGEgY29sdW1uYSBlbiBhZGVsYW50ZS4gICANCi0gVXNhIGxhIGZ1bmNpw7NuIGBtYXAyX2RmY2AgZGVsIHBhcXVldGUgYHB1cnJyYCBwYXJhIGRpdmlkaXIgY2FkYSBwYXIgZGUgY29sdW1uYXMgY29ycmVzcG9uZGllbnRlcyBkZSBkZjEgeSBkZjIsIG11bHRpcGxpY2FuZG8gZWwgcmVzdWx0YWRvIHBvciAxMDAwLiAgICAgDQotIFNlIHJlY29uc3RydXllIGVsIGRhdGEuZnJhbWUgcmVzdWx0YW50ZSBjb21iaW5hbmRvIGxhIHByaW1lcmEgY29sdW1uYSBkZSBkZjEgY29uIGxhcyBjb2x1bW5hcyByZXN1bHRhbnRlcyBkZSBsYSBkaXZpc2nDs24uICAgDQoNCmBgYHtyfQ0KI1BvYmxhY2nDs24gVG90YWwgIA0KVC5Qb2JsYWNpb24gPC0gcmVhZC54bHN4KHBhc3RlMChoZXJlOjpoZXJlKCksICIvQmFzZSBkZSBkYXRvcy9SZXN1bHRhZG9zIEVOT0UueGxzeCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJQb2JsYWNpw7NuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgY29sTmFtZXMgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBkZXRlY3REYXRlcyA9IFRSVUUpDQojIFZlY3RvciBkZSB0aWVtcG8NClBlcmlvZG8gPC0gVC5Qb2JsYWNpb24kUGVyaW9kbyAjU2UgZ3VhcmRhIGVsIHZlY3RvciB0aWVtcG8NCg0KI0NyZWFtb3MgdW5hIGZ1bmNpw7NuIHBlcnNvbmFsaXphZGEgcGFyYSBkaXZpZGlyIGxvcyBlbGVtZW50b3MgZGVzZGUgbGEgc2VndW5kYSBjb2x1bW5hIGVuIGFkZWxhbnRlDQpkaXZpZGVfY29sdW1ucyA8LSBmdW5jdGlvbihkZjEsIGRmMikgew0KICAgICAgICAgICAgICAgICAgICBkZjFfY29scyA8LSBkZjFbLCAyOm5jb2woZGYxKV0NCiAgICAgICAgICAgICAgICAgICAgZGYyX2NvbHMgPC0gZGYyWywgMjpuY29sKGRmMildDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAjIEFwbGljYW1vcyBsYSBkaXZpc2nDs24gdXNhbmRvIG1hcDINCiAgICAgICAgICAgICAgICAgICAgcmVzdWx0X2NvbHMgPC0gbWFwMl9kZmMoZGYxX2NvbHMsIGRmMl9jb2xzLCB+IC54IC8gLnkgKiAxMDAwKQ0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgIyBSZWNvbnN0cnVpbW9zIGVsIGRhdGEuZnJhbWUgY29uIGxhIHByaW1lcmEgY29sdW1uYSBkZSBkZjEgeSBsYXMgY29sdW1uYXMgcmVzdWx0YW50ZXMNCiAgICAgICAgICAgICAgICAgICAgcmVzdWx0IDwtIGJpbmRfY29scyhkZjFbLCAxLCBkcm9wID0gRkFMU0VdLCByZXN1bHRfY29scykNCiAgICAgICAgICAgICAgICAgICAgcmVzdWx0DQp9DQoNCnRhYmxhcyA8LSBscyhwYXR0ZXJuID0gIlQuIikNCmZvcihpIGluIDE6Nil7DQogIGFzc2lnbihwYXN0ZTAodGFibGFzW2ldKSwgZGl2aWRlX2NvbHVtbnMoZ2V0KHBhc3RlMCh0YWJsYXNbaV0pKSwgVC5Qb2JsYWNpb24pKQ0KfQ0KYGBgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCiMgVG9kbyBlbiB1biBkYXRhLmZyYW1lDQpteWRhdGEgPC0gZG8uY2FsbChjYmluZC5kYXRhLmZyYW1lLCBsaXN0KFQuVHJhYmFqbywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVC5Fc3R1ZGlvICU+JSBzZWxlY3QoLWMoIlBlcmlvZG8iKSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBULlVuaW9uICU+JSBzZWxlY3QoLWMoIlBlcmlvZG8iKSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBULkRpdm9yY2lvICU+JSBzZWxlY3QoLWMoIlBlcmlvZG8iKSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBULkZhbWlsaWEgJT4lIHNlbGVjdCgtYygiUGVyaW9kbyIpKSkpDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnRhYmxhIDwtIGhlYWQobXlkYXRhWzE6Nl0pDQprbml0cjo6a2FibGUodGFibGEsDQogICAgICAgICAgICAgZGlnaXRzID0gMiwNCiAgICAgICAgICAgICBhbGlnbiA9ICJjIiwgDQogICAgICAgICAgICAgY2FwdGlvbiA9ICJUYXNhcyBkZSBtaWdyYWNpw7NuIHBvciBhbGfDum4gbW90aXZvIGRlIGF1c2VuY2lhIikgJT4lDQprYWJsZV9zdHlsaW5nKHBvc2l0aW9uID0gImNlbnRlciIsICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiLCAiYm9yZGVyZWQiLCAiaG92ZXIiKSwNCiAgICAgICAgICAgICAgICBmb250X3NpemUgPSAxMCkgJT4lDQprYWJsZV9jbGFzc2ljKGZ1bGxfd2lkdGggPSBGQUxTRSwgaHRtbF9mb250ID0gIkNlbnR1cnkgR290aGljIikNCmBgYA0KDQpBIGNvbnRpbnVhY2nDs24gc2UgZXN0cnVjdHVyYSBsYSBqZXJhcnF1w61hIGRlIGxvcyBuaXZlbGVzIGRlIGFjdWVyZG8gYWwgdGlwbyBkZSBkZXNhZ3JlZ2FjacOzbiBnZW9ncsOhZmljYSwgZW4gbGEgY3VhbCBzZSBhZ3J1cGFuIGxhcyAzMiBjaXVkYWRlcyBhdXRvcmVwcmVzZW50YWRhcyBlbiByZWdpb25lcy4gICAgDQotIFNlIGNvbnNpZGVyYXJvbiA1IHJlZ2lvbmVzIGRlbCBwYcOtcyBwYXJhIHF1ZSBsb3MgY8OhbGN1bG9zIG5vIGZ1ZXJhbiB0YW4gZXh0ZW5zb3MgYSBsYSBob3JhIGRlIGludGVycHJldGFybG9zLiAgIA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KdGFibGEgPC0gZGF0YS5mcmFtZShSZWdpb25lcyA9IGMocmVwKCJDZW50cm8iLCA3KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiTm9yZXN0ZSIsIDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJOb3JvZXN0ZSIsIDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJPY2NpZGVudGUiLCA4KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlN1cmVzdGUiLCA3KSksDQogICAgICAgICAgICAgICAgICAgIENWRV9DaXVkYWQgPSBjKCIxMSIsIAkiMjQiLCAJIjAxIiwgCSIzMiIsIAkiMDQiLCAJIjE0IiwgCSIyOSIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIxIiwgCSIwMyIsIAkiMDYiLCAJIjE1IiwgCSIwOSIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjA4IiwgCSIxOSIsIAkiMjAiLCAJIjMwIiwgCSIxOCIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjEyIiwgCSIyNyIsIAkiMDIiLCAJIjA1IiwgCSIxMyIsIAkiMjgiLCAJIjIyIiwgCSIyNiIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjMxIiwgCSIyMyIsIAkiMDciLCAJIjI1IiwgCSIxNyIsIAkiMTAiLCAJIjE2IiksDQogICAgICAgICAgICAgICAgICAgIENpdWRhZCA9IGMoIkFjYXB1bGNvIiwgCSJDdWVybmF2YWNhIiwgCSJNw6l4aWNvIiwgCSJQYWNodWNhIiwgCSJQdWVibGEiLCAJIlRvbHVjYSIsIAkiVGxheGNhbGEiLCAJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkR1cmFuZ28iLCAJIk1vbnRlcnJleSIsIAkiU2FuIEx1aXMgUG90b3PDrSIsIAkiU2FsdGlsbG8iLCAJIlRhbXBpY28iLCAJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoaWh1YWh1YSIsIAkiQ3VsaWFjw6FuIiwgCSJIZXJtb3NpbGxvIiwgCSJMYSBQYXoiLCAJIlRpanVhbmEiLCAJDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFndWFzY2FsaWVudGVzIiwgCSJDb2xpbWEiLCAJIkd1YWRhbGFqYXJhIiwgCSJMZcOzbiIsIAkiTW9yZWxpYSIsIAkiUXVlcsOpdGFybyIsIAkiVGVwaWMiLCAJIlphY2F0ZWNhcyIsIAkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2FuY8O6biIsIAkiQ2FtcGVjaGUiLCAJIk3DqXJpZGEiLCAJIk9heGFjYSIsIAkiVHV4dGxhIEd1dXRpw6lycmV6IiwgCSJWZXJhY3J1eiIsIAkiVmlsbGFoZXJtb3NhIikpDQoNCnRhYmxhJT4lDQprYWJsZShhbGlnbiA9ICJjIiwNCiAgICAgIGNvbC5uYW1lcyA9IGMoIlJlZ2nDs24iLCAiQ2xhdmUiLCAiQ2l1ZGFkIiksDQogICAgICBjYXB0aW9uPSAiRXN0cnVjdHVyYSBnZW5lcmFsIGRlIGxhcyByZWdpb25lcyIpICU+JQ0KIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIsICJib3JkZXJlZCIsICJob3ZlciIpLA0KICAgICAgICAgICAgICAgZm9udF9zaXplID0gNywNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIsDQogICAgICAgICAgICAgICBsYXRleF9vcHRpb25zPSAiSE9MRF9wb3NpdGlvbiIpICU+JSANCiAgZ3N1YigiZm9udC1zaXplOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgImZvbnQtc2l6ZTogMTBwdCAhaW1wb3J0YW50OyIsIC4pICU+JQ0KICAgZ3N1YigidGV4dC1hbGlnbjogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJ0ZXh0LWFsaWduOiBqdXN0aWZ5ICFpbXBvcnRhbnQ7IiwgLikNCmBgYA0KDQojIyBFc3RydWN0dXJhIGplcsOhcnF1aWNhICANCg0KQ2FkYSB1bm8gZGUgZXN0b3MgZ3J1cG9zIHNlIGRlc2dsb3NhbiBlbiBjYXRlZ29yw61hcyBxdWUgZXN0w6FuIGFuaWRhZGFzIGRlbnRybyBkZSBsYXMgY2F0ZWdvcsOtYXMgZGUgZ3J1cG9zIG3DoXMgZ3JhbmRlcyBjb21vIDMyIGNpdWRhZGVzIGF1dG9yZXByZXNlbnRhZGFzIHkgNSByZWdpb25lcywgcG9yIGxvIHF1ZSBzZSBoYWNlIHVuYSByZWNvbGVjY2nDs24gZGUgMTYwIHNlcmllcyBkZSB0aWVtcG8gcXVlIHNpZ3VlbiB1bmEgZXN0cnVjdHVyYSBkZSBhZ3JlZ2FjacOzbiBqZXLDoXJxdWljYS4gICANCg0KIVtFc3F1ZW1hIEplcsOhcnF1aWNvXShHcmFmaWNvcy9SZWdpw7NuLmpwZyl7d2lkaHQ9MTAwJSxoZWlnaHQ9MTAwJX0gDQoNCkVsIG7Dum1lcm8gZGUgc2VyaWVzIGVuIGVsIG5pdmVsIGluZmVyaW9yIGVzIGRlIDE2MCBzZXJpZXMsIHBvciBsbyBxdWUgbGFzIG9ic2VydmFjaW9uZXMgZW4gZWwgbml2ZWwgw7psdGltbyBzdW1hcmFuIGEgbGFzIG9ic2VydmFjaW9uZXMgZGVsIG5pdmVsIGFudGVyaW9yIHkgYXPDrSBzdWNlc2l2YW1lbnRlLiAgIA0KDQpMb3MgNSBtb3Rpdm9zIGRlIGxhIGF1c2VuY2lhIHNlIHRyYW5zZm9ybWFuIGVuIHNlcmllcyBkZSB0aWVtcG8sIHBhcmEgYW5hbGl6YXJsb3MgY2FkYSB1bm8gcG9zdGVyaW9ybWVudGUuIExvcyBkYXRvcyBzZSBjb252aWVydGVuIGVuIG9iamV0b3MgZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGB0c2ApIHV0aWxpemFuZG8gbGEgZnVuY2nDs24gYHRzYC4gQ2FkYSBzZXJpZSB0ZW1wb3JhbCBzZSBkZWZpbmUgY29uOg0KDQotIGBzdGFydCA9IDIwMDVgOiBFbCBwcmltZXIgYcOxbyBkZSBsYSBzZXJpZSB0ZW1wb3JhbCBlcyAyMDA1LiAgIA0KLSBgZW5kID0gMjAxOWA6IEVsIMO6bHRpbW8gYcOxbyBkZSBsYSBzZXJpZSB0ZW1wb3JhbCBlcyAyMDE5LiAgIA0KLSBgZnJlcXVlbmN5ID0gNGA6IExhIGZyZWN1ZW5jaWEgZGUgbGEgc2VyaWUgdGVtcG9yYWwgZXMgdHJpbWVzdHJhbCAoNCB0cmltZXN0cmVzIHBvciBhw7FvKS4gICAgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnRzLlRyYWJham8gPC0gdHMoVC5UcmFiYWpvICU+JSBzZWxlY3QoLiwgYygyOmxlbmd0aCguKSkpLCBzdGFydCA9IDIwMDUsIGVuZCA9IDIwMTksIGZyZXF1ZW5jeSA9IDQpDQp0cy5Fc3R1ZGlvIDwtIHRzKFQuRXN0dWRpbyAlPiUgc2VsZWN0KC4sIGMoMjpsZW5ndGgoLikpKSwgc3RhcnQgPSAyMDA1LCBlbmQgPSAyMDE5LCBmcmVxdWVuY3kgPSA0KQ0KdHMuVW5pb24gPC0gdHMoVC5VbmlvbiAlPiUgc2VsZWN0KC4sIGMoMjpsZW5ndGgoLikpKSwgc3RhcnQgPSAyMDA1LCBlbmQgPSAyMDE5LCBmcmVxdWVuY3kgPSA0KQ0KdHMuRGl2b3JjaW8gPC0gdHMoVC5EaXZvcmNpbyAlPiUgc2VsZWN0KC4sIGMoMjpsZW5ndGgoLikpKSwgc3RhcnQgPSAyMDA1LCBlbmQgPSAyMDE5LCBmcmVxdWVuY3kgPSA0KQ0KdHMuRmFtaWxpYSA8LSB0cyhULkZhbWlsaWEgJT4lIHNlbGVjdCguLCBjKDI6bGVuZ3RoKC4pKSksIHN0YXJ0ID0gMjAwNSwgZW5kID0gMjAxOSwgZnJlcXVlbmN5ID0gNCkNCmBgYA0KDQojIE1vdGl2byBkZSBsYSBhdXNlbmNpYTogYFRyYWJham9gDQoNClNlIGFuYWxpemEgY8OzbW8gY2FzbyBwYXJ0aWN1bGFyIGVsIG1vdGl2byBkZSBsYSAqKmF1c2VuY2lhIHBvciB0cmFiYWpvKiosIHBhcmEgZW1wZXphciAgZmFtaWxpYXJpemFyc2UgY29uIGxhIGplcmFycXVpemFjacOzbiBkZWwgbW9kZWxvIHkgcG9zdGVyaW9ybWVudGUgYWdyZWdhciBkZSBtYW5lcmEgZ2VuZXJhbCBsb3MgZGVtw6FzIG1vdGl2b3MgZXhwdWVzdG9zIGFsIGluaWNpby4gICAgIA0KDQpVdGlsaXphbmRvIGxhIGZ1bmNpw7NuIGBkeWdyYXBoYCBwZXJtaXRlIG9ic2VydmFyIGRlIG1hbmVyYSBpdGVyYXRpdmEgbXVsdGlwbGVzIHNlcmllcyBkZSB0aWVtcG8uICAgICANCg0KLSBgZHlSYW5nZVNlbGVjdG9yKClgOiBBZ3JlZ2EgdW4gc2VsZWN0b3IgZGUgcmFuZ28gKHVuIGNvbnRyb2wgZGVzbGl6YW50ZSkgcXVlIHBlcm1pdGUgYWwgdXN1YXJpbyBzZWxlY2Npb25hciB1biByYW5nbyBkZSBmZWNoYXMgcGFyYSB2aXN1YWxpemFyIGVuIGVsIGdyw6FmaWNvLiAgICANCi0gYGR5TGVnZW5kKHdpZHRoID0gNjUwKWA6IEHDsWFkZSB1bmEgbGV5ZW5kYSBhbCBncsOhZmljbyB5IGVzdGFibGVjZSBzdSBhbmNobyBhIDY1MCBww614ZWxlcy4gICANCi0gYGR5T3B0aW9ucyhjb2xvcnMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoMzIsICJTZXQyIikpYDogUGVyc29uYWxpemEgbG9zIGNvbG9yZXMgZGUgbGFzIHNlcmllcyBlbiBlbCBncsOhZmljbyB1dGlsaXphbmRvIGxhIHBhbGV0YSBkZSBjb2xvcmVzICJTZXQyIiBkZSBSQ29sb3JCcmV3ZXIsIHF1ZSBwcm9wb3JjaW9uYSB1bmEgcGFsZXRhIGRlIDMyIGNvbG9yZXMuICAgICANCi0gYGR5SGlnaGxpZ2h0KGhpZ2hsaWdodFNlcmllc09wdHMgPSBsaXN0KHN0cm9rZVdpZHRoID0gMikpYDogUGVybWl0ZSByZXNhbHRhciBsYXMgc2VyaWVzIGVuIGVsIGdyw6FmaWNvIGN1YW5kbyBlbCB1c3VhcmlvIHBhc2EgZWwgY3Vyc29yIHNvYnJlIGVsbGFzLiBgc3Ryb2tlV2lkdGggPSAyYCBlc3RhYmxlY2UgZWwgZ3Jvc29yIGRlIGxhIGzDrW5lYSByZXNhbHRhZGEgYSAyIHDDrXhlbGVzLiAgICAgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpHLlRyYWJham8gPC0gZHlncmFwaCh0cy5UcmFiYWpvLCBtYWluID0gIlRyYWJham8iLCAgeWxhYiA9ICJNaWdyYW50ZXMiLCB4bGFiID0gIlBlcmlvZG8iKSAlPiUNCiAgICAgICAgICAgICAgZHlSYW5nZVNlbGVjdG9yKCkgJT4lDQogICAgICAgICAgICAgICBkeUxlZ2VuZCh3aWR0aCA9IDY1MCkgJT4lDQogICAgICAgICAgICAgICAgZHlPcHRpb25zKGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCgzMiwgIlNldDIiKSkgJT4lDQogICAgICAgICAgICAgICAgIGR5SGlnaGxpZ2h0KGhpZ2hsaWdodFNlcmllc09wdHMgPSBsaXN0KHN0cm9rZVdpZHRoID0gMikpDQpHLlRyYWJham8NCmBgYA0KDQpgYGB7ciwgb3V0LndpZHRoPSAiMTEwJSIsIGZpZy5hbGlnbj0nY2VudGVyJyxmaWcuY2FwPSAiTW90aXZvIGRlIHRyYWJham8iLCBldmFsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJHcmFmaWNvcy9HcmFmaWNvIFRyYWJham8ucG5nIikNCmBgYA0KDQpBIGNvbnRpbnVhY2nDs24sIHNlIHByZXNlbnRhIGRlIG1hbmVyYSBkZXNhZ3JlZ2FkYSB1biBhbsOhbGlzaXMgZGVzY3JpcHRpdm8gZGUgbGFzIDMyIGNpdWRhZGVzIGF1dG9yZXByZXNlbnRhZGFzLiAgDQoNCmBgYHtyLGZpZy5hbGlnbj0nY2VudGVyJywgZWNobyA9IEZBTFNFfQ0KdGFibGEgPC0gbXlkYXRhWywgZ3JlcGwoIlRyYWJham8iLCBuYW1lcyhteWRhdGEpKV0NCg0Ka2FibGUoZGVzY3JpYmUodGFibGEpLA0KICAgICAgZGlnaXRzID0gMiwNCiAgICAgICBjYXB0aW9uID0gIkFuw6FsaXNpcyBkZXNjcmlwdGl2bzogTW90aXZvIGRlIHRyYWJham8iKSAlPiUNCiBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgDQogICAgICAgICAgICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiY29uZGVuc2VkIiksDQogICAgICAgICAgICAgICBmb250X3NpemUgPSA4LA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgICAgICAgICAgIGxhdGV4X29wdGlvbnM9ICJIT0xEX3Bvc2l0aW9uIikgJT4lDQogIGthYmxlX2NsYXNzaWMoZnVsbF93aWR0aCA9IEYsIGh0bWxfZm9udCA9ICJDZW50dXJ5IEdvdGhpYyIpICU+JSANCiAgIGdzdWIoImZvbnQtc2l6ZTogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJmb250LXNpemU6IDEwcHQgIWltcG9ydGFudDsiLCAuKSAlPiUNCiAgICBnc3ViKCJ0ZXh0LWFsaWduOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgInRleHQtYWxpZ246IGp1c3RpZnkgIWltcG9ydGFudDsiLCAuKQ0KYGBgDQoNCioqRWplbXBsbyoqOiBQb3IgY2F1c2FzIGRlIHRyYWJham8gbGEgY2l1ZGFkIGRlIEFjYXB1bGNvIG11ZXN0cmEgdW5hIG1lZGlhIGRlIDQuNjIgcGVyc29uYXMgcXVlIGVtaWdyYXJvbiBwb3IgdHJhYmFqbyBkZSBjYWRhIDEwMDAgcGVyc29uYXMuICAgDQoNCiMjIFNlcmllIGRlIHRpZW1wbyBqZXLDoXJxdWljYSAgIA0KDQpTZSB1dGlsaXphIGxhIGZ1bmNpw7NuIGBodHNgIHBhcmEgY3JlYXIgdW5hIHNlcmllIGRlIHRpZW1wbyBqZXLDoXJxdWljYS4gDQoNCioqRGVmaW5pY2nDs24gZGUgdmVjdG9yZXMqKjogIA0KDQotIGBSZWdpb25lc2A6IFVuIHZlY3RvciBxdWUgY29udGllbmUgY8OzZGlnb3MgZGUgcmVnaW9uZXMgcmVwZXRpZG9zIHBhcmEgY3JlYXIgdW5hIGV0aXF1ZXRhIGRlIHJlZ2nDs24gZXNwZWPDrWZpY2EuICANCi0gYENpdWRhZGVzYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBjw7NkaWdvcyBkZSBjaXVkYWRlcyBxdWUgc2UgY29tYmluYW4gY29uIGxhcyByZWdpb25lcyBwYXJhIGNyZWFyIG5vbWJyZXMgw7puaWNvcy4gIA0KLSBgTW90aXZvYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBlbCBtb3Rpdm8gIlRyYWJham8iLCByZXBldGlkbyBwYXJhIGlndWFsYXIgbGEgbG9uZ2l0dWQgZGUgbG9zIG90cm9zIHZlY3RvcmVzLiAgIA0KDQoqKkNyZWFjaW9uIGRlbCBub21icmUgZGUgY29sdW1uYXMqKiAgDQoNClNlIHV0aWxpemFuIGxvcyBkYXRvcyBkZSDDumx0aW1vIG5pdmVsIHkgc2UgdXRpbGl6YSBlbCBhcmd1bWVudG8gYGNoYXJhY3RlcnNgIGRvbmRlIGxvcyBwcmltZXJvcyBkb3MgY2FyYWN0ZXJlcyBjb3JyZXNwb25kZW4gYWwgcHJpbWVyIG5pdmVsIChgUmVnacOzbmApLCBsb3Mgc2lndWllbnRlcyBkb3MgY29ycmVzcG9uZGVuIGFsIHNlZ3VuZG8gbml2ZWwgKGBDaXVkYWRlc2ApIHkgY29tbyDDumx0aW1vIGxvcyBzaWV0ZSBjYXJhY3RlcmVzIGNvcnJlc3BvbmRlbiBhbCBtb3Rpdm8gZGUgbGEgYXVzZW5jaWEgKGBUcmFiYWpvYCkuICAgDQoNCi0gYGh0cyh0cy5UcmFiYWpvLCBub2RlcyA9IGxpc3QoMzIpLCBjaGFyYWN0ZXJzID0gYygyLCAyLCA3KSlgOiBDcmVhIHVuIG1vZGVsbyBqZXLDoXJxdWljbyBkZSBzZXJpZXMgdGVtcG9yYWxlcyAoYGh0c2ApIGEgcGFydGlyIGRlIHRzLlRyYWJham8uICAgIA0KLSBgbm9kZXMgPSBsaXN0KDMyKWA6IERlZmluZSB1biBzb2xvIG5pdmVsIGVuIGxhIGplcmFycXXDrWEgKGBuaXZlbCAxYCkgY29uIDMyIG5vZG9zLiAgICAgDQotIGBjaGFyYWN0ZXJzID0gYygyLCAyLCA3KWA6IERlZmluZSBsYSBlc3RydWN0dXJhIGRlIGxvcyBub21icmVzIGRlIGxhcyBjb2x1bW5hcyBlbiB0w6lybWlub3MgZGUgY2FyYWN0ZXJlcyBwYXJhIGxhIGByZWdpw7NuKDIpYCwgYGNpdWRhZCgyKWAgeSBgbW90aXZvKDcpYC4gICAgDQotIGBNb2RlbG8xJGxhYmVscyRMZXZlbCAxIDwtIGMoIkNlbnRybyIsICJOb3Jlc3RlIiwgIk5vcm9lc3RlIiwgIlN1cmVzdGUiLCAiT2NjaWRlbnRlIilgOiBBc2lnbmEgZXRpcXVldGFzIGEgbG9zIG5vZG9zIGVuIGVsICpuaXZlbCAxKiBkZWwgbW9kZWxvIE1vZGVsbzEuIEVzdGFzIGV0aXF1ZXRhcyByZXByZXNlbnRhbiBkaWZlcmVudGVzIHJlZ2lvbmVzIG8gw6FyZWFzIGdlb2dyw6FmaWNhcyBlbiBsdWdhciBkZSBsb3MgY8OzZGlnb3Mgb3JpZ2luYWxlcy4gICAgIA0KDQoNCmBgYHtyLCBlY2hvID1UUlVFfQ0KI0NhbWJpYW1vcyBsb3Mgbm9tYnJlcyBkZSBsYXMgY29sdW1uYXMgDQpSZWdpb25lcyA8LSBjKHJlcCgiQ0UiLCA3KSwNCiAgICAgICAgICAgICAgcmVwKCJORSIsIDUpLCANCiAgICAgICAgICAgICAgcmVwKCJOVyIsIDUpLCANCiAgICAgICAgICAgICAgcmVwKCJXRSIsIDgpLA0KICAgICAgICAgICAgICByZXAoIlNPIiwgNykpDQpDaXVkYWRlcyA8LSBjKCIxMSIsIAkiMjQiLCAJIjAxIiwgICIzMiIsIAkiMDQiLCAJIjE0IiwgCSIyOSIsIAkNCiAgICAgICAgICAgICAgIjIxIiwgCSIwMyIsIAkiMDYiLCAJIjE1IiwgCSIwOSIsIAkNCiAgICAgICAgICAgICAgIjA4IiwgCSIxOSIsIAkiMjAiLCAJIjMwIiwgCSIxOCIsIAkNCiAgICAgICAgICAgICAgIjEyIiwgCSIyNyIsIAkiMDIiLCAJIjA1IiwgCSIxMyIsIAkiMjgiLCAJIjIyIiwgCSIyNiIsIAkNCiAgICAgICAgICAgICAgIjMxIiwgCSIyMyIsIAkiMDciLCAJIjI1IiwgCSIxNyIsIAkiMTAiLCAJIjE2IikNCk1vdGl2byA8LSBjKHJlcCgiVHJhYmFqbyIsIDMyKSkNCg0Kbm9tYnJlcyA8LSBwYXN0ZTAoUmVnaW9uZXMsIENpdWRhZGVzLCBNb3Rpdm8pICMjIExhcmdvIGRlIDExIC9SZWdpb25lcz0yLENpdWRhZGVzPTIsTW90aXZvPTcNCmNvbG5hbWVzKHRzLlRyYWJham8pIDwtIG5vbWJyZXMNCg0KI05vZG9zIA0KTW9kZWxvMSA8LSBodHModHMuVHJhYmFqbywgbm9kZXMgPSBsaXN0KDMyKSwgY2hhcmFjdGVycyA9IGMoMiwgMiwgNykpDQoNCiMjIENhbWJpYW1vcyBsYXMgZXRpcXVldGFzIA0KTW9kZWxvMSRsYWJlbHMkYExldmVsIDFgIDwtIGMoIkNlbnRybyIsICJOb3Jlc3RlIiwgIk5vcm9lc3RlIiwgIlN1cmVzdGUiLCAiT2NjaWRlbnRlIikNCmBgYA0KDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCmNsYXNzKE1vZGVsbzEpDQpzdW1tYXJ5KE1vZGVsbzEpDQojcDwtc21hdHJpeChNb2RlbG8xKSAjUmVzdW1lbiBkZSBsYSBtYXRyaXogZGUgaGllcmFycXVpY2FsIHRpbWUgc2VyaWVzDQojcTwtYWxsdHMoTW9kZWxvMSkgI01hdHJpeCBkZSB0b2RvcyBsb3Mgbml2ZWxlcw0KYGBgDQoNCiMjIE5pdmVsIDE6IFJlZ2nDs24gDQoNClNlIHZpc3VhbGl6YW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZSB1biBtb2RlbG8gamVyw6FycXVpY28gZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGBNb2RlbG8xYCkuICAgDQoNCi0gYGFnZ3RzKGxldmVsID0gMSlgOiBFeHRyYWUgbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZWwgbml2ZWwgMSBkZWwgbW9kZWxvIE1vZGVsbzEuIEVsIGBsZXZlbCA9IDEgYGluZGljYSBxdWUgc2UgZXN0w6EgZXh0cmF5ZW5kbyBkYXRvcyBkZWwgbml2ZWwgbcOhcyBhbHRvIGVuIGxhIGplcmFycXXDrWEuICAgICAgDQoNCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KTW9kZWxvMSAlPiUgDQogYWdndHMobGV2ZWwgPSAxKSAlPiUNCiAgYXV0b3Bsb3Qoc2l6ZSA9IDEpICsgDQogICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwNCiAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgImxpbmVzIikpICsNCiAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKyANCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoNSwgIkRhcmsyIikpICsgDQogICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDE5LCBieSA9IDMpKSArDQogICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyIsDQogICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICB4ID0gICJZZWFyIiwNCiAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpMYSBncsOhZmljYSBzdXBlcmlvciBtdWVzdHJhIGxhIHRhc2EgZGUgbWlncmFjacOzbiBwb3IgdHJhYmFqbyB0b3RhbCBwb3IgcmVnacOzbi4gRG9uZGUgc2UgcHVlZGUgYXByZWNpYXIgcXVlIGxhIHJlZ2nDs24gTm9yZXN0ZSB5IE5vcm9lc3RlIHByZXNlbnRhbiB1bmEgbWVub3IgbW9pdmlsaWRhZCBjb24gcmVzcGVjdG8gYSBsYXMgZGVtw6FzLiANCg0KDQojIyBOaXZlbCAyOiBDaXVkYWQgYXV0b3JlcHJlc2VudGFkYQ0KDQpBIGNvbnRpbnVhY2nDs24gc2UgbXVldHJhbiBsb3MgZGF0b3MgZGVzZ2xvc2Fkb3MgcG9yIGxhcyAzMiBjaXVkYWRlcy4gDQoNCi0gYGFnZ3RzKGxldmVsID0gMilgOiBpbmRpY2EgcXVlIHNlIGVzdMOhbiBleHRyYXllbmRvIGRhdG9zIGRlIHVuIG5pdmVsIGRlIGplcmFycXXDrWEgaW5mZXJpb3IgYWwgbml2ZWwgMS4gIA0KDQpgYGB7cn0NCk1vZGVsbzEgJT4lIA0KIGFnZ3RzKGxldmVsID0gMikgJT4lDQogIGF1dG9wbG90KHNpemUgPSAwLjUpICsgDQogICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhbWlseSA9ICJDZW50dXJ5IEdvdGhpYyIpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICBsZWdlbmQuc3BhY2luZy54ID0gdW5pdCgwLjEsICJjbSIpLA0KICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSwNCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJEYXJrMiIpKSg2MCkpICsgDQogICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxNSkpICsNCiAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyIsDQogICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpIA0KYGBgDQoNClNpIGJpZW4gbGEgZ3LDoWZpY2EgYW50ZXJpb3Igbm8gcGVybWl0ZSBzdSBpbnRlcnByZXRhYmlsaWRhZCBkZWJpZG8gYSBxdWUgdG9kbyBlbCBlbnNhbWJsZSBkZSBsYXMgc2VyaWVzIGVzdMOhbiBtdXkganVudGFzLiANCg0KSGFjaWVuZG8gdXNvIGRlIGxhIGZ1bmNpw7NuIGBhZ2d0c2AgZXh0cmFlIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBkZSB1biBvYmpldG8gYGh0c2AgcGFyYSBjdWFscXVpZXIgbml2ZWwgZGUgZGVzYWdyZWdhY2nDs24uIFBhcmEgYGFnZ3RzKE1vZGVsbzEsIGxldmVsID0gMilgLCBzZSBlc3BlY2lmaWNhIHF1ZSBxdWVyZW1vcyBleHRyYWVyIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBkZWwgbml2ZWwgMiBkZWwgbW9kZWxvIGplcsOhcnF1aWNvLiBMb3Mgbml2ZWxlcyBlbiB1biBtb2RlbG8gamVyw6FycXVpY28gY29ycmVzcG9uZGVuIGEgZGlmZXJlbnRlcyBuaXZlbGVzIGRlIGFncmVnYWNpw7NuIGVuIGxhIGplcmFycXXDrWEgZGUgZGF0b3MuICAgDQoNClBhcmEgZXN0ZSBjYXNvLCBzZSBlc3TDoW4gdHJhYmFqYW5kbyBjb24gZG9zIG5pdmVsZXMgZGUgZGVzYWdyZWdhY2nDs24gKFJlZ2lvbmVzIHkgQ2l1ZGFkZXMpIHkgYmllbiB1biBOaXZlbCBDZXJvIChUb3RhbCkuICAgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCmdyb3VwcyA8LSBhZ2d0cyhNb2RlbG8xLCBsZXZlbCA9IDIpDQpgYGANCg0KRW4gZWwgc2lndWllbnRlIGdyw6FmaWNvIHNlIG11ZXN0cmFuIGxhcyBzZXJpZXMgZGUgdGllbXBvIGRlbCBuaXZlbCBpbmZlcmlvciwgZXMgZGVjaXIsIGxhcyB0YXNhcyBkZSBtaWdyYWNpw7NuIHBvciB0cmFiYWpvIHBhcmEgY2FkYSB1bmEgZGUgbGFzIGNpdWRhZGVzIGVuIHN1cyByZXNwZWN0aXZhcyByZWdpb25lcy4gICAgDQoNCkF5dWRhbmRvIGFzw60gYSB2aXN1YWxpemFyIGRlIG1hbmVyYSBpbmRpdmlkdWFsIGxhcyBzZXJpZXMuICAgIA0KDQpgYGB7ciwgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDV9DQp0aWJibGU6OmFzX3RpYmJsZShncm91cHMpICU+JQ0KIHRpZHlyOjpnYXRoZXIoU2VyaWVzKSAlPiUNCiAgbXV0YXRlKERhdGUgPSByZXAodGltZShncm91cHMpLCBOQ09MKGdyb3VwcykpLA0KICAgICAgICAgR3JvdXAgPSBzdHJpbmdyOjpzdHJfZXh0cmFjdChTZXJpZXMsICIoW0EtWmEteiBdKikiKSkgJT4lDQogICBnZ3Bsb3QoYWVzKHggPSBEYXRlLCB5ID0gdmFsdWUsIGdyb3VwID0gU2VyaWVzLCBjb2xvdXIgPSBTZXJpZXMpKSArDQogICAgZ2VvbV9saW5lKCkgKyANCiAgICAgdGhlbWVfY2xhc3NpYygpICsNCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICBsZWdlbmQuc3BhY2luZy54ID0gdW5pdCgwLjEsICJjbSIpLA0KICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpLA0KICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArIA0KICAgICAgICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJTZXQyIikpKDMzKSkgKyANCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTgwLCAyMDE1LCBieSA9IDUpKSArDQogICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICAgICAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkgKw0KICAgICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8iLA0KICAgICAgICAgICAgICAgIHkgPSAiUmF0ZSIsDQogICAgICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICAgICBjb2xvciA9ICJHcnVwb3MiKSArDQogICAgICAgICAgICBmYWNldF93cmFwKC4gfiBHcm91cCkNCmBgYA0KDQojIyBGb3JlY2FzdGluZzogTW90aXZvIGRlIHRyYWJham8NCg0KVXRpbGl6YW5kbyBsYSBmdW5jacOzbiBgZm9yZWNhc3QoKWAgZGVsIHBhcXVldGUgYGh0c2AuICANCg0KU2UgcHJlc2VudGFuIHRyZXMgb3BjaW9uZXMgaW50ZWdyYWRhcyBwYXJhIHByb2R1Y2lyIHByb27Ds3N0aWNvcyB1c2FuZG8gZWwgcGFyw6FtZXRybyBgZm1ldGhvZGA6IA0KDQotICoqRVRTKiogYEV4cG9uZW50aWFsIFNtb290aGluZ2AsICAgDQotIE1vZGVsb3MgYEFSSU1BYCANCi0gQ2FtaW5hdGFzIGFsZWF0b3JpYXMoYFJXYCkuICAgICANCg0KIyMjIEVuZm9xdWVzIFteMl0NClteMl06KEZvcmVjYXN0aW5nIEhpZXJhcmNoaWNhbCBUaW1lIFNlcmllcyB1c2luZyBSIC0gQnJpbGxpbyBEYXRhIFNjaWVuY2UgLSBNZWRpdW0uIChuLmQuKS4gUmV0cmlldmVkIE1hcmNoIDMxLCAyMDIwLCBmcm9tIGh0dHBzOi8vbWVkaXVtLmNvbS9icmlsbGlvLWRhdGEtc2NpZW5jZS9mb3JlY2FzdGluZy1oaWVyYXJjaGljYWwtdGltZS1zZXJpZXMtdXNpbmctci01OTg4MjhkYmE0MzUpDQoNCi0gKkVuZm9xdWUgZGUgYWJham8gaGFjaWEgYXJyaWJhKiAqKiJib3R0b20tdXAiKiooYG1ldGhvZD0gImJ1ImApOiBQcm9ub3N0aWNhIGRlbCBuaXZlbCBtw6FzIGJham8gZGUgbGEgamVyYXJxdcOtYSwgZXMgZGVjaXIsIGxvcyBtb3Rpdm9zIGRlIGF1c2VuY2lhIHkgbHVlZ28gdmEgYWdyZWdhbmRvIGxvcyByZXN1bHRhZG9zIGEgbGEgamVyw6FycXXDrWEgZ2VuZXJhciBlbCBwcm9ub3N0aWNvIGRlbCBuaXZlbCBzdXBlcmlvciBhbCDDumx0aW1vLiAgIA0KDQotICpFbmZvcXVlIGRlIGFycmliYSBoYWNpYSBhYmFqbyogKioidG9wLWRvd24iKiogKGBtZXRob2Q9ICJ0ZGZwImApOiBQcm9ub3N0aWNhIGVuIGxhIGplcmFycXXDrWEgZGVsIG5pdmVsIG3DoXMgYWx0bywgZXMgZGVjaXIsIHBvciByZWdpb25lcyB5IGx1ZWdvIHZhIGRlc2dsb3NhbmRvIGxvcyByZXN1bHRhZG9zIGVuIGxhIGplcmFycXXDrWEuICAgIA0KDQotICpFbmZvcXVlIGludGVybWVkaW8qICoqIm1pZGRsZS1vdXQiIChgbWV0aG9kPSAibW8iYCk6IENvbWJpbmEgZW5mb3F1ZXMgYXNjZW5kZW50ZXMgeSBkZXNjZW5kZW50ZXMuIFByaW1lcm8sIHNlIGVsaWdlIHVuICJuaXZlbCBtZWRpbyIgeSBzZSBnZW5lcmFuIHByb27Ds3N0aWNvcyBwYXJhIHRvZGFzIGxhcyBzZXJpZXMgZW4gZXN0ZSBuaXZlbC4gUGFyYSBsYXMgc2VyaWVzIHBvciBlbmNpbWEgZGVsIG5pdmVsIG1lZGlvLCBzZSBnZW5lcmFuIHByb27Ds3N0aWNvcyBjb2hlcmVudGVzIHV0aWxpemFuZG8gZWwgZW5mb3F1ZSBkZSBhYmFqbyBoYWNpYSBhcnJpYmEgYWdyZWdhbmRvIGxvcyBwcm9uw7NzdGljb3MgZGUgIm5pdmVsIG1lZGlvIiBoYWNpYSBhcnJpYmEuIFBhcmEgbGFzIHNlcmllcyBwb3IgZGViYWpvIGRlbCAibml2ZWwgbWVkaW8iLCBzZSBnZW5lcmFuIHByb27Ds3N0aWNvcyBjb2hlcmVudGVzIHV0aWxpemFuZG8gdW4gZW5mb3F1ZSBkZSBhcnJpYmEgaGFjaWEgYWJham8gYWwgZGVzZ2xvc2FyIGxvcyBwcm9uw7NzdGljb3MgZGUgIm5pdmVsIG1lZGlvIiBoYWNpYSBhYmFqby4gICAgICAgIA0KLSBgbWV0aG9kID0gInRkZnAiYDogRXNwZWNpZmljYSBlbCBtw6l0b2RvIGRlIHByb27Ds3N0aWNvIGEgdXRpbGl6YXIuICJ0ZGZwIiBzZSByZWZpZXJlIGEgInRvcC1kb3duIGZvcmVjYXN0aW5nIHVzaW5nIGEgZGV0YWlsZWQgZm9yZWNhc3QgcHJvY2VkdXJlIi4gRXN0ZSBtw6l0b2RvIHJlYWxpemEgZWwgcHJvbsOzc3RpY28gYSBuaXZlbCBtw6FzIGRldGFsbGFkbyBwcmltZXJvIHkgbHVlZ28gYWdyZWdhIGxvcyBwcm9uw7NzdGljb3MgaGFjaWEgbG9zIG5pdmVsZXMgc3VwZXJpb3JlcyBkZSBsYSBqZXJhcnF1w61hLiAgICANCi0gYGggPSA0YDogRGVmaW5lIGVsIGhvcml6b250ZSBkZSBwcm9uw7NzdGljby4gRW4gZXN0ZSBjYXNvLCBzZSBlc3TDoSBwcm9ub3N0aWNhbmRvIDQgcGVyw61vZG9zIGhhY2lhIGVsIGZ1dHVyby4gICAgDQotIGBrZWVwLmZpdHRlZCA9IFRSVUVgOiBNYW50aWVuZSBsb3MgdmFsb3JlcyBhanVzdGFkb3MgZGVsIG1vZGVsbyBwYXJhIHN1IGFuw6FsaXNpcyBwb3N0ZXJpb3IsIGxvIGN1YWwgcHVlZGUgc2VyIMO6dGlsIHBhcmEgZXZhbHVhciBlbCByZW5kaW1pZW50byBkZWwgbW9kZWxvLiAgICANCg0KYGBge3IsIGVjaG8gPSBUUlVFfQ0KI2g8PC1mb3JlY2FzdCBob3Jpem9uDQojbWV0aG9kPSAibW8iPDwtIm1pZGRsZS1vdXQiDQpmLm1vZGVsbzEgPC0gZm9yZWNhc3QoTW9kZWxvMSwgaCA9IDQsIG1ldGhvZCA9ICJ0ZGZwIiwgZm1ldGhvZCA9ICJldHMiLCBwYXJhbGxlbCA9IFRSVUUsIGtlZXAuZml0dGVkID0gVFJVRSkNCmBgYA0KDQpgYGB7cixlY2hvID0gVFJVRX0NCmNsYXNzKGYubW9kZWxvMSkNCiNzdW1tYXJ5KGYubW9kZWxvMSkNCmBgYA0KDQojIyMgTml2ZWwgMCBhbCAyICAgIA0KDQpTZSBleHRyYWVuIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBwYXJhIGxvcyBuaXZlbGVzIDAsIDEgeSAyIHRhbnRvIGRlbCBtb2RlbG8gZGUgcHJvbsOzc3RpY28gKGBmY3N0MWApIGNvbW8gZGVsIG1vZGVsbyBvcmlnaW5hbCAoYGdyb3Vwc2ApLiBFc3RvIHRlIHBlcm1pdGlyw6EgY29tcGFyYXIgbG9zIGRhdG9zIG9yaWdpbmFsZXMgY29uIGxvcyBwcm9uw7NzdGljb3MgZ2VuZXJhZG9zIGEgZGlmZXJlbnRlcyBuaXZlbGVzIGRlIGxhIGplcmFycXXDrWEuICAgIA0KLSBgbGV2ZWxzID0gMDoyYDogRXNwZWNpZmljYSBxdWUgc2UgZGViZW4gZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgcGFyYSBsb3Mgbml2ZWxlcyAwLCAxIHkgMiBkZWwgbW9kZWxvIGplcsOhcnF1aWNvLiAgICANCg0KYGBge3IsZWNobyA9IFRSVUV9DQpmY3N0MSA8LSBhZ2d0cyhmLm1vZGVsbzEsIGxldmVscyA9IDA6MikNCmdyb3VwcyA8LSBhZ2d0cyhNb2RlbG8xLCBsZXZlbHMgPSAwOjIpDQpgYGANCg0KU2UgdmlzdWFsaXphbiB0YW50byBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgcHJvbm9zdGljYWRhcyAoZmNzdDEpIGNvbW8gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIG9yaWdpbmFsZXMgKGdyb3VwcykuICAgDQoNCmBgYHtyLGZpZy53aWR0aCA9IDgsZmlnLmhlaWdodCA9IDV9DQphdXRvcGxvdChmY3N0MSwgc2l6ZSA9IDAuNSkgKw0KIGF1dG9sYXllcihncm91cHMpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxOSwgY29sb3IgPSAiI0E4QUJENyIsIGxpbmV0eXBlPSAiZGFzaGVkIikgKw0KICAgdGhlbWVfY2xhc3NpYygpICsNCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhbWlseSA9ICJDZW50dXJ5IEdvdGhpYyIpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgImxpbmVzIiksDQogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKyANCiAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNSwgMjAyNSwgYnkgPSAyKSkgKw0KICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogICAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkrDQogICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIiwNCiAgICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikgDQpgYGANCg0KQWhvcmEgYmllbiwgc2UgY29tYmluYW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIG9yaWdpbmFsZXMgeSBsb3MgcHJvbsOzc3RpY29zIGVuIHVuYSBzb2xhIHNlcmllIHRlbXBvcmFsLCBtYW50ZW5pZW5kbyBsYSBtaXNtYSBmcmVjdWVuY2lhIHkgcHVudG8gZGUgcGFydGlkYSBxdWUgbGFzIHNlcmllcyBvcmlnaW5hbGVzLiAgDQoNCmBgYHtyLGVjaG8gPSBUUlVFfQ0KdGFibGEgPC0gdHMocmJpbmQoZ3JvdXBzLCBmY3N0MSksIHN0YXJ0ID0gc3RhcnQoZ3JvdXBzKSwgZnJlcXVlbmN5ID0gNCkNCmBgYA0KDQojIyMgTml2ZWwgVG90YWw6IFBvciBtb3Rpdm8gZGUgdHJhYmFqbyAgIA0KDQpBIGNvbnRpbnVhY2nDs24gc2UgbXVldHJhbiBsb3MgZGF0b3MgZGVzZ2xvc2Fkb3MgYSBuaXZlbCBOYWNpb25hbC4gICAgDQoNCmBgYHtyfQ0KI2h0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS9nZ3Bsb3QyLWxpbmUtdHlwZXMtaG93LXRvLWNoYW5nZS1saW5lLXR5cGVzLW9mLWEtZ3JhcGgtaW4tci1zb2Z0d2FyZQ0KYXV0b3Bsb3QodGFibGFbLCAiVG90YWwiXSwgY29sb3VyID0gICIjMTcyMEI3Iiwgc2l6ZSA9IDEuMiwgYWxwaGEgPSAwLjYsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyMDE5LjUsIGNvbG9yID0gIiNBOEFCRDciLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDUsIDIwMjUsIGJ5ID0gMikpICsNCiAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyIsDQogICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgeCA9ICAiWWVhciIsDQogICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpgYGB7cixmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gNX0NCmFzX3RpYmJsZSh0YWJsYVssLTFdKSAlPiUNCiB0aWR5cjo6Z2F0aGVyKFNlcmllcykgJT4lDQogIG11dGF0ZShEYXRlID0gcmVwKHRpbWUodGFibGEpLCBOQ09MKHRhYmxhKS0xKSwNCiAgICAgICAgIEdyb3VwID0gc3RyX2V4dHJhY3QoU2VyaWVzLCAiKFtBLVphLXogXSopIikpICU+JQ0KICAgZ2dwbG90KGFlcyh4ID0gRGF0ZSwgeSA9IHZhbHVlLCBncm91cCA9IFNlcmllcywgY29sb3VyID0gU2VyaWVzKSkgKw0KICAgIGdlb21fbGluZSgpICsNCiAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxNywgY29sb3IgPSAiI0E4QUJENyIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpKSArDQogICAgICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsNCiAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTk4NSwgMjAyNSwgYnkgPSAxMCkpICsNCiAgICAgICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxNSkpKw0KICAgICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8iLA0KICAgICAgICAgICAgICAgIHkgPSAiUmF0ZSIsDQogICAgICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSArDQogICAgICAgICAgICBmYWNldF93cmFwKC5+R3JvdXApIA0KYGBgDQoNClNlIGV4dHJhZW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIHBhcmEgbG9zIG5pdmVsZXMgMCwgMSB5IDIgdGFudG8gZGVsIG1vZGVsbyBkZSBwcm9uw7NzdGljbyAoYGYubW9kZWxvMWApLiBFc3RvIHRlIHBlcm1pdGlyw6EgY29tcGFyYXIgbG9zIGRhdG9zIG9yaWdpbmFsZXMgY29uIGxvcyBwcm9uw7NzdGljb3MgZ2VuZXJhZG9zIGEgZGlmZXJlbnRlcyBuaXZlbGVzIGRlIGxhIGplcmFycXXDrWEuIA0KDQotIGBsZXZlbHMgPSAwOjJgOiBFc3BlY2lmaWNhIHF1ZSBzZSBkZWJlbiBleHRyYWVyIGxhcyBzZXJpZXMgdGVtcG9yYWxlcyBwYXJhIGxvcyBuaXZlbGVzIDAsIDEgeSAyIGRlbCBtb2RlbG8gamVyw6FycXVpY28uICAgICAgDQoNCmBgYHtyLGV2YWw9RkFMU0V9DQpmLm1vZGVsbzEgJT4lIA0KIGFnZ3RzKGxldmVscyA9IDA6MikgJT4lDQogIGF1dG9wbG90KGZhY2V0ID0gRkFMU0UpICsgDQogICB0aGVtZV9jbGFzc2ljKCkgKw0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LCBmYW1pbHkgPSAiQ2VudHVyeSBHb3RoaWMiKSwNCiAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIkNlbnR1cnkgR290aGljIiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcsIGZhbWlseSA9ICJDZW50dXJ5IEdvdGhpYyIpLA0KICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSkgKw0KICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArDQogICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIiwNCiAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikNCmBgYA0KDQojIE1vdGl2b3MgZGUgYXVzZW5jaWEgZW4gZ2VuZXJhbA0KDQpVdGlsaXphbmRvIGxvcyA1IG1vdGl2b3MgZGUgYXVzZW5jaWE6IA0KLSBUcmFiYWpvICAgICANCi0gRXN0dWRpbyAgIA0KLSBTZSBjYXPDsyBvIHVuacOzICAgICANCi0gU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyAgICANCi0gUmV1bmlyc2UgY29uIGxhIGZhbWlsaWEgIA0KDQoqKlNlcmllIGRlIHRpZW1wbyoqICANCg0KTG9zIGRhdG9zIGRlIGxhIGVzdHJ1Y3R1cmEgZ2VuZXJhbCBzZSBjb252aWVydGVuIGVuIG9iamV0b3MgZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGB0c2ApIHV0aWxpemFuZG8gbGEgZnVuY2nDs24gYHRzYC4gQ2FkYSBzZXJpZSB0ZW1wb3JhbCBzZSBkZWZpbmUgY29uOiAgICANCg0KLSBgc3RhcnQgPSAyMDA1YDogRWwgcHJpbWVyIGHDsW8gZGUgbGEgc2VyaWUgdGVtcG9yYWwgZXMgMjAwNS4gICANCi0gYGVuZCA9IDIwMTlgOiBFbCDDumx0aW1vIGHDsW8gZGUgbGEgc2VyaWUgdGVtcG9yYWwgZXMgMjAxOS4gICANCi0gYGZyZXF1ZW5jeSA9IDRgOiBMYSBmcmVjdWVuY2lhIGRlIGxhIHNlcmllIHRlbXBvcmFsIGVzIHRyaW1lc3RyYWwgKDQgdHJpbWVzdHJlcyBwb3IgYcOxbykuICAgDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCnRzLm15ZGF0YSA8LSB0cyhteWRhdGEgJT4lIHNlbGVjdCguLCBjKDI6bmNvbCguKSkpLCBzdGFydCA9IDIwMDUsIGVuZCA9IDIwMTksIGZyZXF1ZW5jeSA9IDQpDQpgYGANCg0KIyMgU2VyaWVzIGRlIHRpZW1wbyBwb3IgbW90aXZvcyBkZSBsYSBtaWdyYWNpw7NuICAgDQoNCiMjIyBNb3Rpdm8gZGUgdHJhYmFqbyAgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpHLlRyYWJham8gPC0gZHlncmFwaCh0cy5UcmFiYWpvLCBtYWluID0gIlRyYWJham8iLCB5bGFiID0gIk1pZ3JhbnRlcyIsIHhsYWIgPSAiUGVyaW9kbyIpICU+JQ0KICAgICAgICAgICAgICBkeVJhbmdlU2VsZWN0b3IoKSAlPiUNCiAgICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgICBkeU9wdGlvbnMoY29sb3JzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDMyLCAiU2V0MiIpKSAlPiUNCiAgICAgICAgICAgICAgICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAyKSkNCkcuVHJhYmFqbw0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogVHJhYmFqbyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gVHJhYmFqby5wbmciKQ0KYGBgDQoNCg0KIyMjIE1vdGl2byBkZSBlc3R1ZGlvICAgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpHLkVzdHVkaW8gPC0gZHlncmFwaCh0cy5Fc3R1ZGlvLCBtYWluID0gIkVzdHVkaW8iLCB5bGFiID0gIk1pZ3JhbnRlcyIsIHhsYWIgPSAiUGVyaW9kbyIpICU+JQ0KICAgICAgICAgICAgICBkeVJhbmdlU2VsZWN0b3IoKSAlPiUNCiAgICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgICBkeU9wdGlvbnMoY29sb3JzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDMyLCAiU2V0MiIpKSAlPiUNCiAgICAgICAgICAgICAgICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAyKSkNCkcuRXN0dWRpbw0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogRXN0dWRpbyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gRXN0dWRpby5wbmciKQ0KYGBgDQoNCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIGVjaG8gPSBGQUxTRX0NCnRhYmxhIDwtIG15ZGF0YVssIGdyZXBsKCJFc3R1ZGlvIiwgbmFtZXMobXlkYXRhKSldDQoNCmthYmxlKGRlc2NyaWJlKHRhYmxhKSwNCiAgICAgIGRpZ2l0cyA9IDIsDQogICAgICBjYXB0aW9uID0gIkFuYWxpc2lzIGRlc2NyaXB0aXZvOiBFc3R1ZGlvIikgJT4lDQoga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsDQogICAgICAgICAgICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiwgImJvcmRlcmVkIiwgImhvdmVyIiksDQogICAgICAgICAgICAgICBmb250X3NpemUgPSA3LA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgICAgICAgICAgIGxhdGV4X29wdGlvbnM9ICJIT0xEX3Bvc2l0aW9uIikgJT4lIA0KICBnc3ViKCJmb250LXNpemU6IGluaXRpYWwgIWltcG9ydGFudDsiLCAiZm9udC1zaXplOiAxMHB0ICFpbXBvcnRhbnQ7IiwgLikgJT4lDQogICBnc3ViKCJ0ZXh0LWFsaWduOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgInRleHQtYWxpZ246IGp1c3RpZnkgIWltcG9ydGFudDsiLCAuKQ0KYGBgDQoNCiMjIyBNb3Rpdm8gc2UgdW5pw7MgbyBjYXPDsyAgICAgDQoNCg0KYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCkcuVW5pb24gPC0gZHlncmFwaCh0cy5VbmlvbiwgbWFpbiA9ICJTZSB1bmnDsyBvIGNhc8OzIiwgeWxhYiA9ICJNaWdyYW50ZXMiLCB4bGFiID0gIlBlcmlvZG8iKSAlPiUNCiAgICAgICAgICAgIGR5UmFuZ2VTZWxlY3RvcigpICU+JQ0KICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgZHlPcHRpb25zKGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCgzMiwgIlNldDIiKSkgJT4lDQogICAgICAgICAgICAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDIpKQ0KRy5Vbmlvbg0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogU2UgdW5pw7MgbyBjYXPDsyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gVW5pb24ucG5nIikNCmBgYA0KDQoNCg0KYGBge3IsZmlnLmFsaWduPSdjZW50ZXInLCBlY2hvID0gRkFMU0V9DQp0YWJsYSA8LSBteWRhdGFbLCBncmVwbCgiVW5pb24iLCBuYW1lcyhteWRhdGEpKV0NCg0Ka2FibGUoZGVzY3JpYmUodGFibGEpLA0KICAgICAgZGlnaXRzID0gMiwNCiAgICAgIGNhcHRpb24gPSAiQW5hbGlzaXMgZGVzY3JpcHRpdm86IFNlIHVuacOzIG8gY2Fzw7MiKSAlPiUNCiBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwNCiAgICAgICAgICAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiLCAiYm9yZGVyZWQiLCAiaG92ZXIiKSwNCiAgICAgICAgICAgICAgIGZvbnRfc2l6ZSA9IDcsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJjZW50ZXIiLA0KICAgICAgICAgICAgICAgbGF0ZXhfb3B0aW9ucz0gIkhPTERfcG9zaXRpb24iKSAlPiUgDQogIGdzdWIoImZvbnQtc2l6ZTogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJmb250LXNpemU6IDEwcHQgIWltcG9ydGFudDsiLCAuKSAlPiUNCiAgIGdzdWIoInRleHQtYWxpZ246IGluaXRpYWwgIWltcG9ydGFudDsiLCAidGV4dC1hbGlnbjoganVzdGlmeSAhaW1wb3J0YW50OyIsIC4pDQpgYGANCg0KDQojIyMgTW90aXZvIHNlIGRpY29yY2nDsyBvIHNlcGFyw7MgICANCg0KYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCkcuRGl2b3JjaW8gPC0gZHlncmFwaCh0cy5EaXZvcmNpbywgbWFpbiA9ICJTZSBkaWNvcmNpw7MgbyBzZXBhcsOzIiwgeWxhYiA9ICJNaWdyYW50ZXMiLCB4bGFiID0gIlBlcmlvZG8iKSAlPiUNCiAgICAgICAgICAgICAgIGR5UmFuZ2VTZWxlY3RvcigpICU+JQ0KICAgICAgICAgICAgICAgIGR5TGVnZW5kKHdpZHRoID0gNjUwKSAlPiUNCiAgICAgICAgICAgICAgICAgZHlPcHRpb25zKGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCgzMiwgIlNldDIiKSkgJT4lDQogICAgICAgICAgICAgICAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDIpKQ0KRy5EaXZvcmNpbw0KYGBgDQoNCmBgYHtyLG91dC53aWR0aD0gIjEwMCUiLCBmaWcuYWxpZ249J2NlbnRlcicsZmlnLmNhcD0gIk1vdGl2bzogU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gRGl2b3JjaW8ucG5nIikNCmBgYA0KDQpgYGB7cixmaWcuYWxpZ249J2NlbnRlcicsIGVjaG8gPSBGQUxTRX0NCnRhYmxhIDwtIG15ZGF0YVssIGdyZXBsKCJEaXZvcmNpbyIsIG5hbWVzKG15ZGF0YSkpXQ0KDQprYWJsZShkZXNjcmliZSh0YWJsYSksDQogICAgICBkaWdpdHMgPSAyLA0KICAgICAgY2FwdGlvbiA9ICJBbmFsaXNpcyBkZXNjcmlwdGl2bzogU2Ugc2VwYXLDsyBvIGRpdm9yY2nDsyIpICU+JQ0KIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIsICJib3JkZXJlZCIsICJob3ZlciIpLA0KICAgICAgICAgICAgICAgZm9udF9zaXplID0gNywNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIsDQogICAgICAgICAgICAgICBsYXRleF9vcHRpb25zPSAiSE9MRF9wb3NpdGlvbiIpICU+JSANCiAgZ3N1YigiZm9udC1zaXplOiBpbml0aWFsICFpbXBvcnRhbnQ7IiwgImZvbnQtc2l6ZTogMTBwdCAhaW1wb3J0YW50OyIsIC4pICU+JQ0KICAgZ3N1YigidGV4dC1hbGlnbjogaW5pdGlhbCAhaW1wb3J0YW50OyIsICJ0ZXh0LWFsaWduOiBqdXN0aWZ5ICFpbXBvcnRhbnQ7IiwgLikNCmBgYA0KDQoNCiMjIyBNb3Rpdm8gcGFyYSByZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIgIA0KIA0KYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCkcuRmFtaWxpYXIgPC0gZHlncmFwaCh0cy5GYW1pbGlhLCBtYWluID0gIlJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsIHlsYWIgPSAiTWlncmFudGVzIiwgeGxhYiA9ICJQZXJpb2RvIikgJT4lDQogICAgICAgICAgICAgICBkeVJhbmdlU2VsZWN0b3IoKSAlPiUNCiAgICAgICAgICAgICAgICBkeUxlZ2VuZCh3aWR0aCA9IDY1MCkgJT4lDQogICAgICAgICAgICAgICAgIGR5T3B0aW9ucyhjb2xvcnMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoMzIsICJTZXQyIikpICU+JQ0KICAgICAgICAgICAgICAgICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAyKSkNCkcuRmFtaWxpYXINCmBgYA0KDQpgYGB7cixvdXQud2lkdGg9ICIxMDAlIiwgZmlnLmFsaWduPSdjZW50ZXInLGZpZy5jYXA9ICJNb3Rpdm86IFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsIGV2YWwgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkdyYWZpY29zL0dyYWZpY28gRmFtaWxpYXIucG5nIikNCmBgYA0KDQpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBlY2hvID0gRkFMU0V9DQp0YWJsYSA8LSBteWRhdGFbLCBncmVwbCgiRmFtaWxpYXIiLCBuYW1lcyhteWRhdGEpKV0NCg0Ka2FibGUoZGVzY3JpYmUodGFibGEpLA0KICAgICAgZGlnaXRzID0gMiwNCiAgICAgIGNhcHRpb24gPSAiQW5hbGlzaXMgZGVzY3JpcHRpdm86IFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwNCiAgICAgICAgICAgICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiKSwNCiAgICAgICAgICAgICAgICBmb250X3NpemUgPSA3LA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIsDQogICAgICAgICAgICAgICAgbGF0ZXhfb3B0aW9ucz0gIkhPTERfcG9zaXRpb24iKQ0KYGBgDQoNCmBgYHtyLGV2YWw9RkFMU0UsIGVjaG8gPSBGQUxTRX0NCiNodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9keWdyYXBocy9pc3N1ZXMvNzENCnNhdmVXaWRnZXQoRy5UcmFiYWpvLCAiR3JhZmljbyBUcmFiYWpvLmh0bWwiLCBzZWxmY29udGFpbmVkID0gVFJVRSwgbGliZGlyID0gTlVMTCkNCnNhdmVXaWRnZXQoRy5Fc3R1ZGlvLCAiR3JhZmljbyBFc3R1ZGlvLmh0bWwiLCBzZWxmY29udGFpbmVkID0gVFJVRSwgbGliZGlyID0gTlVMTCkNCnNhdmVXaWRnZXQoRy5VbmlvbiwgIkdyYWZpY28gVW5pb24uaHRtbCIsIHNlbGZjb250YWluZWQgPSBUUlVFLCBsaWJkaXIgPSBOVUxMKQ0Kc2F2ZVdpZGdldChHLkRpdm9yY2lvLCAiR3JhZmljbyBEaXZvcmNpby5odG1sIiwgc2VsZmNvbnRhaW5lZCA9IFRSVUUsIGxpYmRpciA9IE5VTEwpDQpzYXZlV2lkZ2V0KEcuRmFtaWxpYXIsICJHcmFmaWNvIEZhbWlsaWFyLmh0bWwiLCBzZWxmY29udGFpbmVkID0gVFJVRSwgbGliZGlyID0gTlVMTCkNCg0Kd2lkdGg8LSAxMDgwDQpoZWlnaHQgPC0gNjEwDQojU2UgY29udmllcnRlbiBkZSBodG1sIGEgLnBkZg0Kd2Vic2hvdCh1cmwgPSAiR3JhZmljbyBUcmFiYWpvLmh0bWwiLCBmaWxlID0gIkdyYWZpY28gVHJhYmFqby5wbmciLA0KICAgICAgICBjbGlwcmVjdCA9IGMoMTAsIDMwLCB3aWR0aCArIDUwLCBoZWlnaHQgKyA1MCksDQogICAgICAgIHZ3aWR0aCA9IHdpZHRoLCANCiAgICAgICAgdmhlaWdodCA9IGhlaWdodCkNCndlYnNob3QodXJsID0gIkdyYWZpY28gRXN0dWRpby5odG1sIiwgZmlsZSA9ICJHcmFmaWNvIEVzdHVkaW8ucG5nIiwNCiAgICAgICAgY2xpcHJlY3QgPSBjKDEwLCAzMCwgd2lkdGggKyA1MCwgaGVpZ2h0ICsgNTApLA0KICAgICAgICB2d2lkdGggPSB3aWR0aCwgDQogICAgICAgIHZoZWlnaHQgPSBoZWlnaHQpDQp3ZWJzaG90KHVybCA9ICJHcmFmaWNvIFVuaW9uLmh0bWwiLCBmaWxlID0gIkdyYWZpY28gVW5pb24ucG5nIiwNCiAgICAgICAgY2xpcHJlY3QgPSBjKDEwLCAzMCwgd2lkdGggKyA1MCwgaGVpZ2h0ICsgNTApLA0KICAgICAgICB2d2lkdGggPSB3aWR0aCwgDQogICAgICAgIHZoZWlnaHQgPSBoZWlnaHQpDQp3ZWJzaG90KHVybCA9ICJHcmFmaWNvIERpdm9yY2lvLmh0bWwiLCBmaWxlID0gIkdyYWZpY28gRGl2b3JjaW8ucG5nIiwNCiAgICAgICAgY2xpcHJlY3QgPSBjKDEwLCAzMCwgd2lkdGggKyA1MCwgaGVpZ2h0ICsgNTApLA0KICAgICAgICB2d2lkdGggPSB3aWR0aCwgDQogICAgICAgIHZoZWlnaHQgPSBoZWlnaHQpDQp3ZWJzaG90KHVybCA9ICJHcmFmaWNvIEZhbWlsaWFyLmh0bWwiLGZpbGUgPSAiR3JhZmljbyBGYW1pbGlhci5wbmciLA0KICAgICAgICBjbGlwcmVjdCA9IGMoMTAsIDMwLCB3aWR0aCArIDUwLCBoZWlnaHQgKyA1MCksDQogICAgICAgIHZ3aWR0aCA9IHdpZHRoLCANCiAgICAgICAgdmhlaWdodCA9IGhlaWdodCkNCmBgYCANCg0KIyMgTW9kZWxvIGplcsOhcnF1aWNvDQoNClNlIHV0aWxpemEgbGEgZnVuY2nDs24gYGh0cygpYCBwYXJhIGNyZWFyIHVuYSBzZXJpZSBkZSB0aWVtcG8gamVyw6FycXVpY2EuIA0KDQpEb25kZSBzZSB1dGlsaXphbiBsb3MgZGF0b3MgZGUgw7psdGltbyBuaXZlbCB5IHNlIHV0aWxpemEgZWwgYXJndW1lbnRvIGBjaGFyYWN0ZXJzYCBkb25kZSBsb3MgcHJpbWVyb3MgZG9zIGNhcmFjdGVyZXMgY29ycmVzcG9uZGVuIGFsIHByaW1lciBuaXZlbCAoUmVnacOzbiksIGxvcyBzaWd1aWVudGVzIGRvcyBjb3JyZXNwb25kZW4gYWwgc2VndW5kbyBuaXZlbCAoQ2l1ZGFkZXMpIHkgY29tbyDDumx0aW1vIGxvcyB0cmVzIGNhcmFjdGVyZXMgY29ycmVzcG9uZGVuIGFsIG1vdGl2byBkZSBsYSBhdXNlbmNpYS4gICANCg0KLSBgVFJBYCA9ICJUcmFiYWpvIiAgIA0KLSBgRVNUYCA9ICJFc3R1ZGlvIiAgIA0KLSBgVU5JYCA9ICJTZSBjYXPDsyBvIHVuacOzIiAgIA0KLSBgRElWYCA9ICJTZSBkaXZvcmNpw7MgbyBzZXBhcsOzIiAgICANCi0gYEZBTWAgPSAiUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiAgIA0KDQoqKkRlZmluaWNpw7NuIGRlIHZlY3RvcmVzOioqICAgDQoNCi0gYFJlZ2lvbmVzYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBjw7NkaWdvcyBkZSByZWdpb25lcyByZXBldGlkb3MgcGFyYSBjcmVhciB1bmEgZXRpcXVldGEgZGUgcmVnacOzbiBlc3BlY8OtZmljYS4NCi0gYENpdWRhZGVzYDogVW4gdmVjdG9yIHF1ZSBjb250aWVuZSBjw7NkaWdvcyBkZSBjaXVkYWRlcyBxdWUgc2UgY29tYmluYW4gY29uIGxhcyByZWdpb25lcyBwYXJhIGNyZWFyIG5vbWJyZXMgw7puaWNvcy4NCi0gYE1vdGl2b2A6IFVuIHZlY3RvciBxdWUgY29udGllbmUgZWwgbW90aXZvIGRlIGxhIGF1c2VuY2lhLCByZXBldGlkbyBwYXJhIGlndWFsYXIgbGEgbG9uZ2l0dWQgZGUgbG9zIG90cm9zIHZlY3RvcmVzLiAgIA0KDQpgYGB7cixlY2hvID0gVFJVRX0NClJlZ2lvbmVzIDwtIHJlcChjKHJlcCgiQ0UiLCA3KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiTkUiLCA1KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiTlciLCA1KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiV0UiLCA4KSwNCiAgICAgICAgICAgICAgICAgIHJlcCgiU08iLCA3KSksIDUpDQpDaXVkYWRlcyA8LSByZXAoYygiMTEiLCAJIjI0IiwgCSIwMSIsIAkiMzIiLCAJIjA0IiwgCSIxNCIsIAkiMjkiLA0KICAgICAgICAgICAgICAgICAgIjIxIiwgCSIwMyIsIAkiMDYiLCAJIjE1IiwgCSIwOSIsDQogICAgICAgICAgICAgICAgICAiMDgiLCAJIjE5IiwgCSIyMCIsIAkiMzAiLCAJIjE4IiwgCQ0KICAgICAgICAgICAgICAgICAgIjEyIiwgCSIyNyIsIAkiMDIiLCAJIjA1IiwgCSIxMyIsIAkiMjgiLCAJIjIyIiwgCSIyNiIsIAkNCiAgICAgICAgICAgICAgICAgICIzMSIsIAkiMjMiLCAJIjA3IiwgCSIyNSIsIAkiMTciLCAJIjEwIiwgCSIxNiIpLCA1KQ0KDQpNb3Rpdm8gPC0gYyhyZXAoIlRSQSIsIDMyKSwNCiAgICAgICAgICAgIHJlcCgiRVNUIiwgMzIpLA0KICAgICAgICAgICAgcmVwKCJVTkkiLCAzMiksDQogICAgICAgICAgICByZXAoIkRJViIsIDMyKSwNCiAgICAgICAgICAgIHJlcCgiRkFNIiwgMzIpKQ0KDQpub21icmVzIDwtIHBhc3RlMChSZWdpb25lcywgQ2l1ZGFkZXMsIE1vdGl2bykgI0xhcmdvIGRlIDcgfCBSZWdpb25lcz0yfENpdWRhZGVzPTJ8TW90aXZvPTMNCmNvbG5hbWVzKHRzLm15ZGF0YSkgPC0gbm9tYnJlcw0KDQpub2RlcyA8LSBsaXN0KDE2MCwgYyg1LCAzMiwgNSkpICMxNjAgdmFyaWFibGVzIHxSZWdpb25lcz01fENpdWRhZGVzPTMyfE1vdGl2b3M9NXwgIA0KTW9kZWxvMiA8LSBodHModHMubXlkYXRhLCBub2RlcyA9IG5vZGVzLGNoYXJhY3RlcnMgPSBjKDIsIDIsIDMpKQ0KDQojQ2FtYmlhbW9zIGxvcyBsYWJlbHMgDQpNb2RlbG8yJGxhYmVscyRgTGV2ZWwgMWAgPC0gYygiQ2VudHJvIiwgIk5vcmVzdGUiLCAiTm9yb2VzdGUiLCAiU3VyZXN0ZSIsICJPY2NpZGVudGUiKQ0KYGBgDQoNCiMjIyBOaXZlbCAxOiBSZWdpw7NuICAgDQoNClNlIHZpc3VhbGl6YW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZSB1biBtb2RlbG8gamVyw6FycXVpY28gZGUgc2VyaWVzIHRlbXBvcmFsZXMgKGBNb2RlbG8xYCkuICAgDQoNCi0gYGFnZ3RzKGxldmVsID0gMSlgOiBFeHRyYWUgbGFzIHNlcmllcyB0ZW1wb3JhbGVzIGFncmVnYWRhcyBkZWwgbml2ZWwgMSBkZWwgbW9kZWxvIE1vZGVsbzEuIEVsIGBsZXZlbCA9IDEgYGluZGljYSBxdWUgc2UgZXN0w6EgZXh0cmF5ZW5kbyBkYXRvcyBkZWwgbml2ZWwgbcOhcyBhbHRvIGVuIGxhIGplcmFycXXDrWEuICAgICAgIA0KDQpgYGB7cn0NCk1vZGVsbzIgJT4lIA0KIGFnZ3RzKGxldmVsID0gMSkgJT4lDQogIGF1dG9wbG90KHNpemUgPSAxKSArIA0KICAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjIsICJjbSIpKSArDQogICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsgDQogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDUsICJEYXJrMiIpKSArIA0KICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNSwgMjAxOSwgYnkgPSAyKSkgKw0KICAgICAgICBsYWJzKHRpdGxlID0gIk1vdGl2byBkZSBsYSBhdXNlbmNpYSAyMDA1LTIwMTkiLA0KICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8gLyBFc3R1ZGlvIC8gU2UgY2Fzw7MgbyB1bmnDsyAvIERpdm9yY2nDsyBvIHNlcGFyw7MgLyBSZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIiLA0KICAgICAgICAgICAgIHkgPSAiUmF0ZSIsDQogICAgICAgICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQojIyBOaXZlbCAyOiBDdWlkYWQgYXV0b3JlcHJlc2VudGFkYSAgICANCg0KQSBjb250aW51YWNpw7NuIHNlIG11ZXRyYW4gbG9zIGRhdG9zIGRlc2dsb3NhZG9zIHBvciBsYXMgMzIgY2l1ZGFkZXMuIA0KDQotIGBhZ2d0cyhsZXZlbCA9IDIpYDogaW5kaWNhIHF1ZSBzZSBlc3TDoW4gZXh0cmF5ZW5kbyBkYXRvcyBkZSB1biBuaXZlbCBkZSBqZXJhcnF1w61hIGluZmVyaW9yIGFsIG5pdmVsIDEuICANCg0KYGBge3J9DQpNb2RlbG8yICU+JSANCiBhZ2d0cyhsZXZlbCA9IDIpICU+JQ0KICBhdXRvcGxvdChzaXplID0gMC41KSArIA0KICAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpLA0KICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArDQogICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoOCwgIkRhcmsyIikpKDYwKSkgKyANCiAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkrDQogICAgICAgbGFicyh0aXRsZSA9ICJNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgMjAwNS0yMDE5IiwNCiAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8gLyBFc3R1ZGlvIC8gU2UgY2Fzw7MgbyB1bmnDsyAvIERpdm9yY2nDsyBvIHNlcGFyw7MgLyBSZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIiLA0KICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgIHggPSAiWWVhciIsDQogICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpTaSBiaWVuIGxhIGdyw6FmaWNhIGFudGVyaW9yIG5vIHBlcm1pdGUgc3UgaW50ZXJwcmV0YWJpbGlkYWQgZGViaWRvIGEgcXVlIHRvZG8gZWwgZW5zYW1ibGUgZGUgbGFzIHNlcmllcyBlc3TDoW4gbXV5IGp1bnRhcy4gDQoNCkhhY2llbmRvIHVzbyBkZSBsYSBmdW5jacOzbiBgYWdndHNgIGV4dHJhZSBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGUgdW4gb2JqZXRvIGBodHNgIHBhcmEgY3VhbHF1aWVyIG5pdmVsIGRlIGRlc2FncmVnYWNpw7NuLiBQYXJhIGBhZ2d0cyhNb2RlbG8xLCBsZXZlbCA9IDIpYCwgc2UgZXNwZWNpZmljYSBxdWUgcXVlcmVtb3MgZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGVsIG5pdmVsIDIgZGVsIG1vZGVsbyBqZXLDoXJxdWljby4gTG9zIG5pdmVsZXMgZW4gdW4gbW9kZWxvIGplcsOhcnF1aWNvIGNvcnJlc3BvbmRlbiBhIGRpZmVyZW50ZXMgbml2ZWxlcyBkZSBhZ3JlZ2FjacOzbiBlbiBsYSBqZXJhcnF1w61hIGRlIGRhdG9zLiANCg0KUGFyYSBlc3RlIGNhc28sIHNlIGVzdMOhbiB0cmFiYWphbmRvIGNvbiBkb3Mgbml2ZWxlcyBkZSBkZXNhZ3JlZ2FjacOzbiAoUmVnaW9uZXMgeSBDaXVkYWRlcykgeSBiaWVuIHVuIE5pdmVsIENlcm8gKFRvdGFsKS4gICANCg0KYGBge3IsZWNobyA9IFRSVUV9DQpncm91cHMgPC0gYWdndHMoTW9kZWxvMiwgbGV2ZWwgPSAyKQ0KYGBgDQoNCmBgYHtyLGZpZy53aWR0aCA9IDEwLGZpZy5oZWlnaHQgPSAxMn0NCnRpYmJsZTo6YXNfdGliYmxlKGdyb3VwcykgJT4lDQogdGlkeXI6OmdhdGhlcihTZXJpZXMpICU+JQ0KICBtdXRhdGUoRGF0ZSA9IHJlcCh0aW1lKGdyb3VwcyksIE5DT0woZ3JvdXBzKSksDQogICAgICAgICBHcm91cCA9c3RyaW5ncjo6c3RyX2V4dHJhY3QoU2VyaWVzLCAiKFtBLVphLXogXSopIikpICU+JQ0KICAgZ2dwbG90KGFlcyh4ID0gRGF0ZSwgeSA9IHZhbHVlLCBncm91cCA9IFNlcmllcywgY29sb3VyID0gU2VyaWVzKSkgKw0KICAgIGdlb21fbGluZSgpICsgDQogICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpLA0KICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICJsaW5lcyIpLA0KICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArDQogICAgICAgI3NjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoOCwgIkRhcmsyIikpKDMzKSkgKyANCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTgwLCAyMDE1LCBieSA9IDUpKSArDQogICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICAgICAgICAgIGd1aWRlcyhjb2wgPSBndWlkZV9sZWdlbmQobmNvbCA9IDE1KSkrDQogICAgICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyAvIEVzdHVkaW8gLyBTZSBjYXPDsyBvIHVuacOzIC8gRGl2b3JjacOzIG8gc2VwYXLDsyAvIFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsDQogICAgICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpICsNCiAgICAgICAgICAgIGZhY2V0X3dyYXAoLiB+IEdyb3VwKSANCmBgYA0KDQojIyBOaXZlbCAzOiBNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgICAgDQoNCkhhY2llbmRvIHVzbyBkZSBsYSBmdW5jacOzbiBgYWdndHNgIGV4dHJhZSBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGUgdW4gb2JqZXRvIGBodHNgIHBhcmEgY3VhbHF1aWVyIG5pdmVsIGRlIGRlc2FncmVnYWNpw7NuLiBQYXJhIGBhZ2d0cyhNb2RlbG8yLCBsZXZlbCA9IDMpYCwgc2UgZXNwZWNpZmljYSBxdWUgcXVlcmVtb3MgZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgZGVsIG5pdmVsIDIzIGRlbCBtb2RlbG8gamVyw6FycXVpY28uIExvcyBuaXZlbGVzIGVuIHVuIG1vZGVsbyBqZXLDoXJxdWljbyBjb3JyZXNwb25kZW4gYSBkaWZlcmVudGVzIG5pdmVsZXMgZGUgYWdyZWdhY2nDs24gZW4gbGEgamVyYXJxdcOtYSBkZSBkYXRvcy4gDQoNCkVuIG1vZGVsbyBnZW5lcmFsLCBzZSBlc3TDoW4gdHJhYmFqYW5kbyBjb24gdHJlcyBuaXZlbGVzIGRlIGRlc2FncmVnYWNpw7NuIChgTW90aXZvIGRlIGF1c2VuY2lhYCwgYFJlZ2lvbmVzYCB5IGBDaXVkYWRlc2ApIHkgYmllbiB1biBOaXZlbCBDZXJvIChgVG90YWxgKS4gICAgDQoNCmBgYHtyLGVjaG8gPSBUUlVFfQ0KZ3JvdXBzIDwtIGFnZ3RzKE1vZGVsbzIsIGxldmVsID0gMykNCmBgYA0KDQpgYGB7cixmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gMTJ9DQojaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL3N0cl9sb2NhdGUuaHRtbA0KdGliYmxlOjphc190aWJibGUoZ3JvdXBzKSAlPiUNCiB0aWR5cjo6Z2F0aGVyKFNlcmllcykgJT4lIA0KICBtdXRhdGUoRGF0ZSA9IHJlcCh0aW1lKGdyb3VwcyksIE5DT0woZ3JvdXBzKSksDQogICAgICAgICBHcm91cCA9c3RyaW5ncjo6c3RyX2V4dHJhY3QoU2VyaWVzLCAiKFtBLVphLXogXSopIiksDQogICAgICAgICBNb3Rpdm89c3RyaW5ncjo6c3RyX3N1YihTZXJpZXMsNSwgNykpICU+JQ0KICAgZ2dwbG90KGFlcyh4ID0gRGF0ZSwgeSA9IHZhbHVlLCBncm91cCA9IFNlcmllcywgY29sb3VyID0gU2VyaWVzKSkgKw0KICAgIGdlb21fbGluZSgpICsgDQogICAgIHRoZW1lX2NsYXNzaWMoKSArDQogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpLA0KICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgICAgICAgbGVnZW5kLmtleS53aWR0aD11bml0KDAuMiwgImNtIiksDQogICAgICAgICAgICBsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMCwgImNtIiksDQogICAgICAgICAgICBsZWdlbmQuc3BhY2luZy54ID0gdW5pdCgwLCAiY20iKSwNCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSwNCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArDQogICAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKw0KICAgICAgICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJEYXJrMiIpKSgxNjApKSArIA0KICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDE5ODAsIDIwMTUsIGJ5ID0gNSkpICsNCiAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogICAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChuY29sID0gMTUpKSsNCiAgICAgICAgICAgbGFicyh0aXRsZSA9ICJNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgMjAwNS0yMDE5IiwNCiAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIC8gRXN0dWRpbyAvIFNlIGNhc8OzIG8gdW5pw7MgLyBEaXZvcmNpw7MgbyBzZXBhcsOzIC8gUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiwNCiAgICAgICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgICAgIHggPSAiWWVhciIsDQogICAgICAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikgKw0KICAgICAgICAgICAgZmFjZXRfd3JhcCguIH4gR3JvdXAgKyBNb3Rpdm8pIA0KYGBgDQoNCkFuYWxpemFuZG8gbGEgZ3LDoWZpY2EgYW50ZXJpb3IgZWwgbW90aXZvIGRlIGF1c2VuY2lhIHBhcmEgIlJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIgZXMgbGEgcXVlIHByZXNlbnRhIHVuIG1heW9yIG7Dum1lcm8gZGUgY2Fzb3MgbWlncmF0b3Jpb3MiIGNvbiByZXNwZWN0byBhIGxvcyBvdHJvcyBjdWF0cm8gY2Fzb3MuICAgICAgDQoNCmBgYHtyfQ0KI3ByaW50KE1vZGVsbzIpDQojc21hdHJpeChNb2RlbG8yKQ0KI2FsbHRzKE1vZGVsbzIpDQpgYGANCg0KIyMgRm9yZWNhc3Rpbmc6IE1vdGl2byBkZSBsYSBhdXNlbmNpYSBlbiBnZW5lcmFsICAgDQoNClNlIHJlYWxpemEgdW4gcHJvbsOzc3RpY28gamVyw6FycXVpY28gc29icmUgYE1vZGVsbzJgIHBhcmEgbG9zIHByw7N4aW1vcyAxMCBwZXJpb2RvcywgdXRpbGl6YW5kbyBlbCBtw6l0b2RvIGRlIGAibWlkZGxlLW91dCJgIHBhcmEgbGEgYWdyZWdhY2nDs24gamVyw6FycXVpY2EgeSBlbCBtb2RlbG8gYEFSSU1BYCBwYXJhIGxvcyBwcm9uw7NzdGljb3MgaW5kaXZpZHVhbGVzLiAgIA0KDQpTZSBlc3BlcmEgcXVlIGxvcyBwcm9uw7NzdGljb3Mgc2VhbiBjb25zaXN0ZW50ZXMgY29uIGxhIGVzdHJ1Y3R1cmEgZGUgYWdyZWdhY2nDs24gZGUgbGFzIHNlcmllcyBkZSAgdGllbXBvIGFsIGFncnVwYXJsYXMuICAgIA0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQojaD1mb3Jlc2Nhc3QgaG9yaXpvbg0KI21ldGhvZDwtIm1vIiwgImJ1IiwgInRkZnAiDQpmLm1vZGVsbzIgPC0gZm9yZWNhc3QoTW9kZWxvMiwgaCA9IDEwLCBtZXRob2QgPSAibW8iLCBsZXZlbCA9IDIsIGZtZXRob2QgPSAiYXJpbWEiLCBwYXJhbGxlbCA9IFRSVUUsIGtlZXAuZml0dGVkID0gVFJVRSkNCmBgYA0KDQpgYGB7cixlY2hvID0gVFJVRSwgZXZhbCA9IEZBTFNFfQ0Kc3VtbWFyeShmLm1vZGVsbzIpDQpgYGANCg0KIyMjIE5pdmVsIDAgYWwgMjogVG90YWwgLyBSZWdpw7NuIC8gQ2l1ZGFkICAgDQoNClNlIGV4dHJhZW4gbGFzIHNlcmllcyB0ZW1wb3JhbGVzIHBhcmEgbG9zIG5pdmVsZXMgMCwgMSB5IDIgdGFudG8gZGVsIG1vZGVsbyBkZSBwcm9uw7NzdGljbyAoYGZjc3QyYCkgY29tbyBkZWwgbW9kZWxvIG9yaWdpbmFsIChgZ3JvdXBzYCkuIEVzdG8gdGUgcGVybWl0aXLDoSBjb21wYXJhciBsb3MgZGF0b3Mgb3JpZ2luYWxlcyBjb24gbG9zIHByb27Ds3N0aWNvcyBnZW5lcmFkb3MgYSBkaWZlcmVudGVzIG5pdmVsZXMgZGUgbGEgamVyYXJxdcOtYS4gICAgIA0KLSBgbGV2ZWxzID0gMDoyYDogRXNwZWNpZmljYSBxdWUgc2UgZGViZW4gZXh0cmFlciBsYXMgc2VyaWVzIHRlbXBvcmFsZXMgcGFyYSBsb3Mgbml2ZWxlcyAwLCAxIHkgMiBkZWwgbW9kZWxvIGplcsOhcnF1aWNvLiAgDQoNCmBgYHtyLGVjaG8gPSBUUlVFfQ0KZmNzdDIgPC0gYWdndHMoZi5tb2RlbG8yLCBsZXZlbHMgPSAwOjIpDQpncm91cHMgPC0gYWdndHMoTW9kZWxvMiwgbGV2ZWxzID0gMDoyKQ0KYGBgDQoNCmBgYHtyLGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gOH0NCmF1dG9wbG90KGZjc3QyLCBzaXplID0gMC41KSArDQogYXV0b2xheWVyKGdyb3VwcykgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyMDE5LGNvbG9yID0gIiNBOEFCRDciLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogICB0aGVtZV9jbGFzc2ljKCkgKw0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLA0KICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAibGluZXMiKSwNCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArIA0KICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDI1LCBieSA9IDIpKSArDQogICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCiAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChuY29sID0gMTUpKSsNCiAgICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgIHN1YnRpdGxlID0gIlRyYWJham8gLyBFc3R1ZGlvIC8gU2UgY2Fzw7MgbyB1bmnDsyAvIERpdm9yY2nDsyBvIHNlcGFyw7MgLyBSZXVuaXJzZSBjb24gdW4gZmFtaWxpYXIiLA0KICAgICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgICAgICBjb2xvciA9ICJTZXJpZXMiKSANCmBgYA0KDQpTZSBjcmVhIHVuYSBzZXJpZSB0ZW1wb3JhbCBjb21iaW5hZGEgZGUgbGFzIHNlcmllcyB0ZW1wb3JhbGVzIG9yaWdpbmFsZXMgeSBsb3MgcHJvbsOzc3RpY29zLiAgIA0KDQpgYGB7cixlY2hvID0gVFJVRX0NCnRhYmxhIDwtIHRzKHJiaW5kKGdyb3VwcywgZmNzdDIpLA0KICAgICAgICAgICAgICAgICAgc3RhcnQgPSBzdGFydChncm91cHMpLCBmcmVxdWVuY3kgPSA0KSAjRnJlY3VlbmNpYSBhbCBhw7FvDQpgYGANCg0KIyMjIE5pdmVsIDA6IFRvdGFsIGRlIGNhc29zIGRlIG1pZ3JhY2nDs24gICANCg0KQSBjb250aW51YWNpw7NuIHNlIG11ZXRyYW4gbG9zIGRhdG9zIGRlc2dsb3NhZG9zIGEgbml2ZWwgTmFjaW9uYWwuICANCg0KYGBge3J9DQojaHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC93aWtpL2dncGxvdDItbGluZS10eXBlcy1ob3ctdG8tY2hhbmdlLWxpbmUtdHlwZXMtb2YtYS1ncmFwaC1pbi1yLXNvZnR3YXJlDQphdXRvcGxvdCh0YWJsYVssICJUb3RhbCJdLCBjb2xvdXIgPSAiIzE3MjBCNyIsIHNpemUgPSAxLjIsIGFscGhhID0gMC42LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArICAgICAgDQogZ2VvbV92bGluZSh4aW50ZXJjZXB0PTIwMTkuNSxjb2xvciA9ICIjQThBQkQ3IixsaW5ldHlwZT0gImRhc2hlZCIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSkgKyANCiAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDI1LCBieSA9IDIpKSArDQogICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyAvIEVzdHVkaW8gLyBTZSBjYXPDsyBvIHVuacOzIC8gRGl2b3JjacOzIG8gc2VwYXLDsyAvIFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsDQogICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpIA0KYGBgDQoNCiMjIyBOaXZlbCAxIGEgMjogTml2ZWwgcmVnacOzbiB5IG5pdmVsIGNpdWRhZCAgDQoNCkEgY29udGludWFjacOzbiBzZSBtdWV0cmFuIGxvcyBkYXRvcyBkZXNnbG9zYWRvcyBhIG5pdmVsIFJlZ2nDs24uICANCg0KYGBge3IsZmlnLndpZHRoID0gMTAsZmlnLmhlaWdodCA9IDV9DQphc190aWJibGUodGFibGFbLC0xXSkgJT4lDQogdGlkeXI6OmdhdGhlcihTZXJpZXMpICU+JQ0KICBtdXRhdGUoRGF0ZSA9IHJlcCh0aW1lKHRhYmxhKSwgTkNPTCh0YWJsYSktMSksDQogICAgICAgICBHcm91cCA9IHN0cl9leHRyYWN0KFNlcmllcywgIihbQS1aYS16IF0qKSIpKSAlPiUNCiAgIGdncGxvdChhZXMoeCA9IERhdGUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBTZXJpZXMsIGNvbG91ciA9IFNlcmllcykpICsNCiAgICBnZW9tX2xpbmUoKSArDQogICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwMTksY29sb3IgPSAiI0E4QUJENyIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSwNCiAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICAgICAgICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMC4yLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMCwgImNtIiksDQogICAgICAgICAgICAgbGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoMC4xLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgImxpbmVzIiksDQogICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsNCiAgICAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKw0KICAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA1LCAyMDI1LGJ5ID0gNSkpICsNCiAgICAgICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxNSkpICsNCiAgICAgICAgICAgbGFicyh0aXRsZSA9ICJNb3Rpdm8gZGUgbGEgYXVzZW5jaWEgMjAwNS0yMDE5IiwNCiAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJUcmFiYWpvIC8gRXN0dWRpbyAvIFNlIGNhc8OzIG8gdW5pw7MgLyBEaXZvcmNpw7MgbyBzZXBhcsOzIC8gUmV1bmlyc2UgY29uIHVuIGZhbWlsaWFyIiwNCiAgICAgICAgICAgICAgICB5ID0gIlJhdGUiLA0KICAgICAgICAgICAgICAgIHggPSAiWWVhciIsDQogICAgICAgICAgICAgICAgY29sb3IgPSAiU2VyaWVzIikgKw0KICAgICAgICAgICAgZmFjZXRfd3JhcCguIH4gR3JvdXApIA0KYGBgDQoNCiMjIyBOaXZlbCAzOiBNb3Rpdm9zIGRlIGF1c2VuY2lhIGVuIGdlbmVyYWwgICB2DQoNCkEgY29udGludWFjacOzbiBzZSBtdWV0cmFuIGxvcyBkYXRvcyBkZXNnbG9zYWRvcyBwb3IgbW90aXZvIGRlIGxhIGF1c2VuY2lhLiAgICANCg0KYGBge3IsZWNobyA9IFRSVUV9DQpmY3N0MyA8LSBhZ2d0cyhmLm1vZGVsbzIsIGxldmVscyA9IDMpDQpncm91cHMgPC0gYWdndHMoTW9kZWxvMiwgbGV2ZWxzID0gMykNCnRhYmxhIDwtIHRzKHJiaW5kKGdyb3VwcywgZmNzdDMpLCBzdGFydCA9IHN0YXJ0KGdyb3VwcyksIGZyZXF1ZW5jeSA9IDQpICNGcmVjdWVuY2lhIGFsIGHDsW8NCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoID0gMTMsZmlnLmhlaWdodCA9IDEzfQ0KYXNfdGliYmxlKHRhYmxhWywtMV0pICU+JQ0KIHRpZHlyOjpnYXRoZXIoU2VyaWVzKSAlPiUNCiAgbXV0YXRlKERhdGUgPSByZXAodGltZSh0YWJsYSksIE5DT0wodGFibGEpIC0gMSksDQogICAgICAgICBHcm91cCA9IHN0cl9leHRyYWN0KFNlcmllcywgIihbQS1aYS16IF0qKSIpLA0KICAgICAgICAgTW90aXZvID0gc3RyaW5ncjo6c3RyX3N1YihTZXJpZXMsIDUsIDcpKSAlPiUNCiAgIGdncGxvdChhZXMoeCA9IERhdGUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBTZXJpZXMsIGNvbG91ciA9IFNlcmllcykpICsNCiAgICBnZW9tX2xpbmUoKSArDQogICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwMTksIGNvbG9yID0gIiNBOEFCRDciLCBsaW5ldHlwZT0gImRhc2hlZCIpICsNCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpLA0KICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LndpZHRoPXVuaXQoMC4yLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMCwgImNtIiksDQogICAgICAgICAgICAgbGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoMC4xLCAiY20iKSwNCiAgICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuMDEsICJsaW5lcyIpLA0KICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArDQogICAgICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsNCiAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNSwgMjAyNSxieSA9IDUpKSArDQogICAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChuY29sID0gMTUpKSArDQogICAgICAgICAgIGxhYnModGl0bGUgPSAiTW90aXZvIGRlIGxhIGF1c2VuY2lhIDIwMDUtMjAxOSIsDQogICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiVHJhYmFqbyAvIEVzdHVkaW8gLyBTZSBjYXPDsyBvIHVuacOzIC8gRGl2b3JjacOzIG8gc2VwYXLDsyAvIFJldW5pcnNlIGNvbiB1biBmYW1pbGlhciIsDQogICAgICAgICAgICAgICAgeSA9ICJSYXRlIiwNCiAgICAgICAgICAgICAgICB4ID0gIlllYXIiLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gIlNlcmllcyIpICsNCiAgICAgICAgICAgIGZhY2V0X3dyYXAoLn4gR3JvdXAgKyBNb3Rpdm8pDQpgYGANCg0KDQojIFJlZmVyZW5jaWFzDQoNCkF0aGFuYXNvcG91bG9zLCBHLCBIeW5kbWFuLCBSSiwgS291cmVudHplcywgTiwgYW5kIFBldHJvcG91bG9zLCBGICgyMDE3KS4gRm9yZWNhc3Rpbmcgd2l0aCBUZW1wb3JhbCBIaWVyYXJjaGllcy4gRXVyb3BlYW4gSm91cm5hbCBvZiBPcGVyYXRpb25hbCBSZXNlYXJjaCAyNjIoMSksIDYw4oCTNzQuICAgDQoNCkNvY2hyYW4sIFcuRy4gKDE5NzcpLCBTYW1wbGluZyBUZWNobmlxdWVzLiBKb25oIFdpbGV5IGFuZCBTb25zLCBOZXcgWW9yay4gICANCg0KRW5jdWVzdGEgTmFjaW9uYWwgZGUgT2N1cGFjacOzbiB5IEVtcGxlbyAoRU5PRSksIHBvYmxhY2nDs24gZGUgMTUgYcOxb3MgeSBtw6FzIGRlIGVkYWQuICgyMDIwKS4gNTAgcHJlZ3VudGFzIHkgcmVzcHVlc3Rhcy4gSW5zdGl0dXRvIE5hY2lvbmFsIGRlIEVzdGFkw61zdGljYSBHZW9ncmFmw61hIGUgSW5mb3Jtw6F0aWNhLiBSZXRyaWV2ZWQgTWF5IDcsIDIwMjAsIGZyb20gaHR0cHM6Ly93d3cuaW5lZ2kub3JnLm14L3Byb2dyYW1hcy9lbm9lLzE1eW1hcy9kZWZhdWx0Lmh0bWwjRG9jdW1lbnRhY2lvbiAgIA0KDQoNCkZvcmVjYXN0aW5nIEhpZXJhcmNoaWNhbCBUaW1lIFNlcmllcyB1c2luZyBSIC0gQnJpbGxpbyBEYXRhIFNjaWVuY2UgLSBNZWRpdW0uIChuLmQuKS4gUmV0cmlldmVkIE1hcmNoIDMwLCAyMDIwLCBmcm9tIGh0dHBzOi8vbWVkaXVtLmNvbS9icmlsbGlvLWRhdGEtc2NpZW5jZS9mb3JlY2FzdGluZy1oaWVyYXJjaGljYWwtdGltZS1zZXJpZXMtdXNpbmctci01OTg4MjhkYmE0MzUgICANCg0KUi4gSi4gSHluZG1hbiBhbmQgQS4gS29laGxlciAoMjAwNiksIEFub3RoZXIgbG9vayBhdCBtZWFzdXJlcyBvZiBmb3JlY2FzdCBhY2N1cmFjeSwgSW50ZXJuYXRpb25hbCBKb3VybmFsIG9mIEZvcmVjYXN0aW5nLCAyMiwgNjc5LTY4OC4gIA0KDQpIeW5kbWFuIFIuSi4sIEFobWVkIFIuQS4sIEF0aGFuYXNvcG91bG9zIEcuLCBTaGFuZyBILkwuLCAoMjAxMSksIE9wdGltYWwgY29tYmluYXRpb24gZm9yZWNhc3RzIGZvciBoaWVyYXJjaGljYWwgdGltZSBzZXJpZXMsIENvbXB1dGF0aW9uYWwgU3RhdGlzdGljcyAmIERhdGEgQW5hbHlzaXMgNTUoOSksIDI1NzkgLTI1ODkuICANCg0KSHluZG1hbiwgUi4gSi4sIEF0aGFuYXNvcG91bG9zLCBHLiwgJiBTaGFuZywgSC4gTC4gKDIwMTQpLiBodHM6IEFuIFIgUGFja2FnZSBmb3IgRm9yZWNhc3RpbmcgSGllcmFyY2hpY2FsIG9yIEdyb3VwZWQgVGltZSBTZXJpZXMuIGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9odHMvdmlnbmV0dGVzL2h0cy5wZGY/Zm9yY2VkZWZhdWx0PXRydWUgICAgICAgDQoNCkh5bmRtYW4sIFJKICgyMDE3KS4gZm9yZWNhc3Q6IEZvcmVjYXN0aW5nIEZ1bmN0aW9ucyBmb3IgVGltZSBTZXJpZXMgYW5kIExpbmVhciBNb2RlbHMuIFIgcGFja2FnZSB2ZXJzaW9uIDguMS4gaHR0cDovL3BrZy5yb2JqaHluZG1hbi5jb20vZm9yZWNhc3QuICAgDQoNCiANCiMgTGlicmVyw61hcyAgDQoNCioqTGlicmVyw61hcyBxdWUgc2UgdXNhcm9uIGVuIGVsIHRyYWJham8qKiAgIA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbmFtZXMoc2Vzc2lvbkluZm8oKSRvdGhlclBrZ3MpDQpgYGANCg0KTm9zIGhhIHNlcnZpZG8gYSBjb25zdHJ1aXIgbW9kZWxvcyBkZSBzZXJpZXMgZGUgdGllbXBvIGNvbiBkYXRvcyBlc3RydWN0dXJhbGVzIHBhcmEgZmluZXMgZGUgcHJvbsOzc3RpY29zLiANCg0KDQoNCjxhIHJlbD0gImxpY2Vuc2UiIGhyZWY9ICJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS80LjAvIj48aW1nIHNyYz0gImh0dHBzOi8vaS5jcmVhdGl2ZWNvbW1vbnMub3JnL2wvYnkvNC4wLzg4eDMxLnBuZyIgYWx0PSAiQ3JlYXRpdmUgQ29tbW9ucyBMaWNlbmNlIiBzdHlsZT0gImJvcmRlci13aWR0aDowIi8+PC9hPjxiciAvPlRoaXMgd29yayBieSBbKipEaWFuYSBWaWxsYXNhbmEgT2NhbXBvKipde3htbG5zOmNjPSAiaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiBwcm9wZXJ0eSA9ICJjYzphdHRyaWJ1dGlvbk5hbWUifSBpcyBsaWNlbnNlZCB1bmRlciBhIDxhIHJlbD0gImxpY2Vuc2UiIGhyZWY9ICJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS80LjAvIj5DcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2U8L2E+Lg0KDQo=